@lobehub/chat 1.133.4 → 1.133.6

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 (55) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/changelog/v1.json +24 -0
  3. package/locales/ar/models.json +7 -1
  4. package/locales/bg-BG/models.json +7 -1
  5. package/locales/de-DE/models.json +7 -1
  6. package/locales/en-US/models.json +7 -1
  7. package/locales/es-ES/models.json +7 -1
  8. package/locales/fa-IR/models.json +7 -1
  9. package/locales/fr-FR/models.json +7 -1
  10. package/locales/it-IT/models.json +7 -1
  11. package/locales/ja-JP/models.json +7 -1
  12. package/locales/ko-KR/models.json +7 -1
  13. package/locales/nl-NL/models.json +7 -1
  14. package/locales/pl-PL/models.json +7 -1
  15. package/locales/pt-BR/models.json +7 -1
  16. package/locales/ru-RU/models.json +7 -1
  17. package/locales/tr-TR/models.json +7 -1
  18. package/locales/vi-VN/models.json +7 -1
  19. package/locales/zh-CN/models.json +7 -1
  20. package/locales/zh-TW/models.json +7 -1
  21. package/package.json +2 -2
  22. package/packages/database/src/models/__tests__/aiModel.test.ts +3 -0
  23. package/packages/database/src/models/aiModel.ts +18 -2
  24. package/packages/model-bank/src/aiModels/aihubmix.ts +41 -1
  25. package/packages/model-bank/src/aiModels/deepseek.ts +12 -12
  26. package/packages/model-bank/src/aiModels/google.ts +225 -2
  27. package/packages/model-bank/src/aiModels/hunyuan.ts +39 -15
  28. package/packages/model-bank/src/aiModels/novita.ts +17 -3
  29. package/packages/model-bank/src/aiModels/siliconcloud.ts +68 -3
  30. package/packages/model-bank/src/types/aiModel.ts +13 -9
  31. package/packages/model-runtime/src/core/ModelRuntime.ts +1 -1
  32. package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +0 -1
  33. package/packages/model-runtime/src/core/streams/protocol.ts +12 -12
  34. package/packages/model-runtime/src/providers/google/createImage.ts +13 -4
  35. package/packages/model-runtime/src/providers/google/index.test.ts +39 -1
  36. package/packages/model-runtime/src/providers/google/index.ts +62 -22
  37. package/packages/model-runtime/src/utils/modelParse.ts +1 -1
  38. package/packages/types/src/auth.ts +2 -0
  39. package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +6 -3
  40. package/src/config/modelProviders/deepseek.ts +4 -7
  41. package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +2 -2
  42. package/src/features/ChatInput/ActionBar/Model/ReasoningTokenSlider.tsx +12 -2
  43. package/src/features/ChatInput/ActionBar/Model/ThinkingBudgetSlider.tsx +29 -3
  44. package/src/server/modules/ModelRuntime/index.test.ts +13 -0
  45. package/src/server/modules/ModelRuntime/index.ts +4 -2
  46. package/src/server/routers/lambda/aiModel.test.ts +2 -0
  47. package/src/services/__tests__/models.test.ts +95 -5
  48. package/src/services/_auth.ts +8 -1
  49. package/src/services/chat/clientModelRuntime.test.ts +68 -17
  50. package/src/services/chat/clientModelRuntime.ts +15 -4
  51. package/src/services/chat/helper.ts +11 -0
  52. package/src/services/chat/index.ts +11 -15
  53. package/src/services/models.ts +14 -4
  54. package/packages/model-runtime/src/utils/usageConverter.test.ts +0 -351
  55. package/packages/model-runtime/src/utils/usageConverter.ts +0 -122
@@ -151,12 +151,14 @@ describe('aiModelRouter', () => {
151
151
  id: 'model-1',
152
152
  providerId: 'provider-1',
153
153
  enabled: true,
154
+ type: 'embedding',
154
155
  });
155
156
 
156
157
  expect(mockToggle).toHaveBeenCalledWith({
157
158
  id: 'model-1',
158
159
  providerId: 'provider-1',
159
160
  enabled: true,
161
+ type: 'embedding',
160
162
  });
161
163
  });
162
164
 
@@ -1,21 +1,111 @@
1
- import { Mock, describe, expect, it, vi } from 'vitest';
1
+ import { Mock, beforeEach, describe, expect, it, vi } from 'vitest';
2
2
 
3
+ import { aiProviderSelectors } from '@/store/aiInfra';
4
+
5
+ import { createHeaderWithAuth } from '../_auth';
6
+ import { initializeWithClientStore } from '../chat/clientModelRuntime';
7
+ import { resolveRuntimeProvider } from '../chat/helper';
3
8
  import { ModelsService } from '../models';
4
9
 
5
10
  vi.stubGlobal('fetch', vi.fn());
6
11
 
7
- // 创建一个测试用的 ModelsService 实例
12
+ vi.mock('@/const/version', () => ({
13
+ isDeprecatedEdition: false,
14
+ }));
15
+
16
+ vi.mock('../_auth', () => ({
17
+ createHeaderWithAuth: vi.fn(async () => ({})),
18
+ }));
19
+
20
+ vi.mock('../chat/helper', () => ({
21
+ resolveRuntimeProvider: vi.fn((provider: string) => provider),
22
+ }));
23
+
24
+ vi.mock('../chat/clientModelRuntime', () => ({
25
+ initializeWithClientStore: vi.fn(),
26
+ }));
27
+
28
+ vi.mock('@/store/aiInfra', () => ({
29
+ aiProviderSelectors: {
30
+ isProviderFetchOnClient: () => () => false,
31
+ },
32
+ getAiInfraStoreState: () => ({}),
33
+ }));
8
34
 
35
+ vi.mock('@/store/user', () => ({
36
+ useUserStore: {
37
+ getState: vi.fn(),
38
+ },
39
+ }));
40
+
41
+ vi.mock('@/store/user/selectors', () => ({
42
+ modelConfigSelectors: {
43
+ isProviderFetchOnClient: () => () => false,
44
+ },
45
+ }));
46
+
47
+ // 创建一个测试用的 ModelsService 实例
9
48
  const modelsService = new ModelsService();
10
49
 
50
+ const mockedCreateHeaderWithAuth = vi.mocked(createHeaderWithAuth);
51
+ const mockedResolveRuntimeProvider = vi.mocked(resolveRuntimeProvider);
52
+ const mockedInitializeWithClientStore = vi.mocked(initializeWithClientStore);
53
+
11
54
  describe('ModelsService', () => {
55
+ beforeEach(() => {
56
+ (fetch as Mock).mockClear();
57
+ mockedCreateHeaderWithAuth.mockClear();
58
+ mockedResolveRuntimeProvider.mockReset();
59
+ mockedResolveRuntimeProvider.mockImplementation((provider: string) => provider);
60
+ mockedInitializeWithClientStore.mockClear();
61
+ });
62
+
12
63
  describe('getModels', () => {
13
- it('should call the appropriate endpoint for a generic provider', async () => {
14
- (fetch as Mock).mockResolvedValueOnce(new Response(JSON.stringify({ models: [] })));
64
+ it('should call the endpoint for runtime provider when server fetching', async () => {
65
+ (fetch as Mock).mockResolvedValueOnce(
66
+ new Response(JSON.stringify({ models: [] }), { status: 200 }),
67
+ );
15
68
 
16
69
  await modelsService.getModels('openai');
17
70
 
18
- expect(fetch).toHaveBeenCalled();
71
+ expect(mockedResolveRuntimeProvider).toHaveBeenCalledWith('openai');
72
+ expect(fetch).toHaveBeenCalledWith('/webapi/models/openai', { headers: {} });
73
+ expect(mockedInitializeWithClientStore).not.toHaveBeenCalled();
74
+ });
75
+
76
+ it('should map custom provider to runtime provider endpoint', async () => {
77
+ mockedResolveRuntimeProvider.mockImplementation(() => 'openai');
78
+ (fetch as Mock).mockResolvedValueOnce(
79
+ new Response(JSON.stringify({ models: [] }), { status: 200 }),
80
+ );
81
+
82
+ await modelsService.getModels('custom-provider');
83
+
84
+ expect(mockedResolveRuntimeProvider).toHaveBeenCalledWith('custom-provider');
85
+ expect(fetch).toHaveBeenCalledWith('/webapi/models/openai', { headers: {} });
86
+ expect(mockedInitializeWithClientStore).not.toHaveBeenCalled();
87
+ });
88
+
89
+ it('should fetch models on client when isProviderFetchOnClient is true', async () => {
90
+ // Mock isProviderFetchOnClient to return true
91
+ const spyIsClient = vi
92
+ .spyOn(aiProviderSelectors, 'isProviderFetchOnClient')
93
+ .mockReturnValue(() => true);
94
+ // Mock initializeWithClientStore to return a runtime with a models() method
95
+ const mockModels = vi.fn().mockResolvedValue({ models: ['model1', 'model2'] });
96
+ mockedInitializeWithClientStore.mockResolvedValue({ models: mockModels } as any);
97
+
98
+ const result = await modelsService.getModels('openai');
99
+
100
+ expect(spyIsClient).toHaveBeenCalledWith('openai');
101
+ expect(mockedInitializeWithClientStore).toHaveBeenCalledWith({
102
+ provider: 'openai',
103
+ runtimeProvider: 'openai',
104
+ });
105
+ expect(mockModels).toHaveBeenCalled();
106
+ expect(result).toEqual({ models: ['model1', 'model2'] });
107
+
108
+ spyIsClient.mockRestore();
19
109
  });
20
110
  });
21
111
  });
@@ -14,6 +14,8 @@ import { useUserStore } from '@/store/user';
14
14
  import { keyVaultsConfigSelectors, userProfileSelectors } from '@/store/user/selectors';
15
15
  import { obfuscatePayloadWithXOR } from '@/utils/client/xor-obfuscation';
16
16
 
17
+ import { resolveRuntimeProvider } from './chat/helper';
18
+
17
19
  export const getProviderAuthPayload = (
18
20
  provider: string,
19
21
  keyVaults: OpenAICompatibleKeyVault &
@@ -104,7 +106,12 @@ export const createPayloadWithKeyVaults = (provider: string) => {
104
106
  keyVaults = aiProviderSelectors.providerKeyVaults(provider)(useAiInfraStore.getState()) || {};
105
107
  }
106
108
 
107
- return getProviderAuthPayload(provider, keyVaults);
109
+ const runtimeProvider = resolveRuntimeProvider(provider);
110
+
111
+ return {
112
+ ...getProviderAuthPayload(runtimeProvider, keyVaults as any),
113
+ runtimeProvider,
114
+ };
108
115
  };
109
116
 
110
117
  export const createXorKeyVaultsPayload = (provider: string) => {
@@ -108,7 +108,10 @@ describe('ModelRuntimeOnClient', () => {
108
108
  },
109
109
  },
110
110
  } as UserSettingsState) as unknown as UserStore;
111
- const runtime = await initializeWithClientStore(ModelProvider.OpenAI, {});
111
+ const runtime = await initializeWithClientStore({
112
+ payload: {},
113
+ provider: ModelProvider.OpenAI,
114
+ });
112
115
  expect(runtime).toBeInstanceOf(ModelRuntime);
113
116
  expect(runtime['_runtime']).toBeInstanceOf(LobeOpenAI);
114
117
  expect(runtime['_runtime'].baseURL).toBe('user-openai-endpoint');
@@ -127,7 +130,10 @@ describe('ModelRuntimeOnClient', () => {
127
130
  },
128
131
  } as UserSettingsState) as unknown as UserStore;
129
132
 
130
- const runtime = await initializeWithClientStore(ModelProvider.Azure, {});
133
+ const runtime = await initializeWithClientStore({
134
+ payload: {},
135
+ provider: ModelProvider.Azure,
136
+ });
131
137
  expect(runtime).toBeInstanceOf(ModelRuntime);
132
138
  expect(runtime['_runtime']).toBeInstanceOf(LobeAzureOpenAI);
133
139
  });
@@ -142,7 +148,10 @@ describe('ModelRuntimeOnClient', () => {
142
148
  },
143
149
  },
144
150
  } as UserSettingsState) as unknown as UserStore;
145
- const runtime = await initializeWithClientStore(ModelProvider.Google, {});
151
+ const runtime = await initializeWithClientStore({
152
+ payload: {},
153
+ provider: ModelProvider.Google,
154
+ });
146
155
  expect(runtime).toBeInstanceOf(ModelRuntime);
147
156
  expect(runtime['_runtime']).toBeInstanceOf(LobeGoogleAI);
148
157
  });
@@ -157,7 +166,10 @@ describe('ModelRuntimeOnClient', () => {
157
166
  },
158
167
  },
159
168
  } as UserSettingsState) as unknown as UserStore;
160
- const runtime = await initializeWithClientStore(ModelProvider.Moonshot, {});
169
+ const runtime = await initializeWithClientStore({
170
+ payload: {},
171
+ provider: ModelProvider.Moonshot,
172
+ });
161
173
  expect(runtime).toBeInstanceOf(ModelRuntime);
162
174
  expect(runtime['_runtime']).toBeInstanceOf(LobeMoonshotAI);
163
175
  });
@@ -174,7 +186,10 @@ describe('ModelRuntimeOnClient', () => {
174
186
  },
175
187
  },
176
188
  } as UserSettingsState) as unknown as UserStore;
177
- const runtime = await initializeWithClientStore(ModelProvider.Bedrock, {});
189
+ const runtime = await initializeWithClientStore({
190
+ payload: {},
191
+ provider: ModelProvider.Bedrock,
192
+ });
178
193
  expect(runtime).toBeInstanceOf(ModelRuntime);
179
194
  expect(runtime['_runtime']).toBeInstanceOf(LobeBedrockAI);
180
195
  });
@@ -189,7 +204,10 @@ describe('ModelRuntimeOnClient', () => {
189
204
  },
190
205
  },
191
206
  } as UserSettingsState) as unknown as UserStore;
192
- const runtime = await initializeWithClientStore(ModelProvider.Ollama, {});
207
+ const runtime = await initializeWithClientStore({
208
+ payload: {},
209
+ provider: ModelProvider.Ollama,
210
+ });
193
211
  expect(runtime).toBeInstanceOf(ModelRuntime);
194
212
  expect(runtime['_runtime']).toBeInstanceOf(LobeOllamaAI);
195
213
  });
@@ -204,7 +222,10 @@ describe('ModelRuntimeOnClient', () => {
204
222
  },
205
223
  },
206
224
  } as UserSettingsState) as unknown as UserStore;
207
- const runtime = await initializeWithClientStore(ModelProvider.Perplexity, {});
225
+ const runtime = await initializeWithClientStore({
226
+ payload: {},
227
+ provider: ModelProvider.Perplexity,
228
+ });
208
229
  expect(runtime).toBeInstanceOf(ModelRuntime);
209
230
  expect(runtime['_runtime']).toBeInstanceOf(LobePerplexityAI);
210
231
  });
@@ -219,7 +240,10 @@ describe('ModelRuntimeOnClient', () => {
219
240
  },
220
241
  },
221
242
  } as UserSettingsState) as unknown as UserStore;
222
- const runtime = await initializeWithClientStore(ModelProvider.Anthropic, {});
243
+ const runtime = await initializeWithClientStore({
244
+ payload: {},
245
+ provider: ModelProvider.Anthropic,
246
+ });
223
247
  expect(runtime).toBeInstanceOf(ModelRuntime);
224
248
  expect(runtime['_runtime']).toBeInstanceOf(LobeAnthropicAI);
225
249
  });
@@ -234,7 +258,10 @@ describe('ModelRuntimeOnClient', () => {
234
258
  },
235
259
  },
236
260
  } as UserSettingsState) as unknown as UserStore;
237
- const runtime = await initializeWithClientStore(ModelProvider.Mistral, {});
261
+ const runtime = await initializeWithClientStore({
262
+ payload: {},
263
+ provider: ModelProvider.Mistral,
264
+ });
238
265
  expect(runtime).toBeInstanceOf(ModelRuntime);
239
266
  expect(runtime['_runtime']).toBeInstanceOf(LobeMistralAI);
240
267
  });
@@ -249,7 +276,10 @@ describe('ModelRuntimeOnClient', () => {
249
276
  },
250
277
  },
251
278
  } as UserSettingsState) as unknown as UserStore;
252
- const runtime = await initializeWithClientStore(ModelProvider.OpenRouter, {});
279
+ const runtime = await initializeWithClientStore({
280
+ payload: {},
281
+ provider: ModelProvider.OpenRouter,
282
+ });
253
283
  expect(runtime).toBeInstanceOf(ModelRuntime);
254
284
  expect(runtime['_runtime']).toBeInstanceOf(LobeOpenRouterAI);
255
285
  });
@@ -264,7 +294,10 @@ describe('ModelRuntimeOnClient', () => {
264
294
  },
265
295
  },
266
296
  } as UserSettingsState) as unknown as UserStore;
267
- const runtime = await initializeWithClientStore(ModelProvider.TogetherAI, {});
297
+ const runtime = await initializeWithClientStore({
298
+ payload: {},
299
+ provider: ModelProvider.TogetherAI,
300
+ });
268
301
  expect(runtime).toBeInstanceOf(ModelRuntime);
269
302
  expect(runtime['_runtime']).toBeInstanceOf(LobeTogetherAI);
270
303
  });
@@ -279,7 +312,10 @@ describe('ModelRuntimeOnClient', () => {
279
312
  },
280
313
  },
281
314
  } as UserSettingsState) as unknown as UserStore;
282
- const runtime = await initializeWithClientStore(ModelProvider.ZeroOne, {});
315
+ const runtime = await initializeWithClientStore({
316
+ payload: {},
317
+ provider: ModelProvider.ZeroOne,
318
+ });
283
319
  expect(runtime).toBeInstanceOf(ModelRuntime);
284
320
  expect(runtime['_runtime']).toBeInstanceOf(LobeZeroOneAI);
285
321
  });
@@ -295,7 +331,10 @@ describe('ModelRuntimeOnClient', () => {
295
331
  },
296
332
  },
297
333
  } as UserSettingsState) as unknown as UserStore;
298
- const runtime = await initializeWithClientStore(ModelProvider.Groq, {});
334
+ const runtime = await initializeWithClientStore({
335
+ payload: {},
336
+ provider: ModelProvider.Groq,
337
+ });
299
338
  expect(runtime).toBeInstanceOf(ModelRuntime);
300
339
  const lobeOpenAICompatibleInstance = runtime['_runtime'] as LobeOpenAICompatibleRuntime;
301
340
  expect(lobeOpenAICompatibleInstance).toBeInstanceOf(LobeGroq);
@@ -314,7 +353,10 @@ describe('ModelRuntimeOnClient', () => {
314
353
  },
315
354
  },
316
355
  } as UserSettingsState) as unknown as UserStore;
317
- const runtime = await initializeWithClientStore(ModelProvider.DeepSeek, {});
356
+ const runtime = await initializeWithClientStore({
357
+ payload: {},
358
+ provider: ModelProvider.DeepSeek,
359
+ });
318
360
  expect(runtime).toBeInstanceOf(ModelRuntime);
319
361
  expect(runtime['_runtime']).toBeInstanceOf(LobeDeepSeekAI);
320
362
  });
@@ -329,7 +371,10 @@ describe('ModelRuntimeOnClient', () => {
329
371
  },
330
372
  },
331
373
  } as UserSettingsState) as unknown as UserStore;
332
- const runtime = await initializeWithClientStore(ModelProvider.Qwen, {});
374
+ const runtime = await initializeWithClientStore({
375
+ payload: {},
376
+ provider: ModelProvider.Qwen,
377
+ });
333
378
  expect(runtime).toBeInstanceOf(ModelRuntime);
334
379
  expect(runtime['_runtime']).toBeInstanceOf(LobeQwenAI);
335
380
  });
@@ -349,7 +394,10 @@ describe('ModelRuntimeOnClient', () => {
349
394
  },
350
395
  },
351
396
  } as any as UserSettingsState) as unknown as UserStore;
352
- const runtime = await initializeWithClientStore('unknown' as ModelProvider, {});
397
+ const runtime = await initializeWithClientStore({
398
+ payload: {},
399
+ provider: 'unknown' as ModelProvider,
400
+ });
353
401
  expect(runtime).toBeInstanceOf(ModelRuntime);
354
402
  expect(runtime['_runtime']).toBeInstanceOf(LobeOpenAI);
355
403
  });
@@ -376,7 +424,10 @@ describe('ModelRuntimeOnClient', () => {
376
424
  },
377
425
  },
378
426
  } as UserSettingsState) as unknown as UserStore;
379
- const runtime = await initializeWithClientStore(ModelProvider.ZhiPu, {});
427
+ const runtime = await initializeWithClientStore({
428
+ payload: {},
429
+ provider: ModelProvider.ZhiPu,
430
+ });
380
431
  expect(runtime).toBeInstanceOf(ModelRuntime);
381
432
  expect(runtime['_runtime']).toBeInstanceOf(LobeZhipuAI);
382
433
  });
@@ -2,15 +2,26 @@ import { ModelRuntime } from '@lobechat/model-runtime';
2
2
 
3
3
  import { createPayloadWithKeyVaults } from '../_auth';
4
4
 
5
+ export interface InitializeWithClientStoreOptions {
6
+ payload?: any;
7
+ provider: string;
8
+ runtimeProvider?: string;
9
+ }
10
+
5
11
  /**
6
12
  * Initializes the AgentRuntime with the client store.
7
- * @param provider - The provider name.
8
- * @param payload - Init options
13
+ * @param options.provider - Provider identifier used to resolve key vaults.
14
+ * @param options.runtimeProvider - Actual runtime implementation key (defaults to provider).
15
+ * @param options.payload - Additional initialization payload.
9
16
  * @returns The initialized AgentRuntime instance
10
17
  *
11
18
  * **Note**: if you try to fetch directly, use `fetchOnClient` instead.
12
19
  */
13
- export const initializeWithClientStore = (provider: string, payload?: any) => {
20
+ export const initializeWithClientStore = ({
21
+ provider,
22
+ runtimeProvider,
23
+ payload,
24
+ }: InitializeWithClientStoreOptions) => {
14
25
  /**
15
26
  * Since #5267, we map parameters for client-fetch in function `getProviderAuthPayload`
16
27
  * which called by `createPayloadWithKeyVaults` below.
@@ -26,7 +37,7 @@ export const initializeWithClientStore = (provider: string, payload?: any) => {
26
37
  * Configuration override order:
27
38
  * payload -> providerAuthPayload -> commonOptions
28
39
  */
29
- return ModelRuntime.initializeWithProvider(provider, {
40
+ return ModelRuntime.initializeWithProvider(runtimeProvider ?? provider, {
30
41
  ...commonOptions,
31
42
  ...providerAuthPayload,
32
43
  ...payload,
@@ -54,3 +54,14 @@ export const isEnableFetchOnClient = (provider: string) => {
54
54
  return aiProviderSelectors.isProviderFetchOnClient(provider)(getAiInfraStoreState());
55
55
  }
56
56
  };
57
+
58
+ export const resolveRuntimeProvider = (provider: string) => {
59
+ if (isDeprecatedEdition) return provider;
60
+
61
+ const isBuiltin = Object.values(ModelProvider).includes(provider as any);
62
+ if (isBuiltin) return provider;
63
+
64
+ const providerConfig = aiProviderSelectors.providerConfigById(provider)(getAiInfraStoreState());
65
+
66
+ return providerConfig?.settings.sdkType || 'openai';
67
+ };
@@ -6,7 +6,7 @@ import { ModelProvider } from 'model-bank';
6
6
 
7
7
  import { enableAuth } from '@/const/auth';
8
8
  import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
9
- import { isDeprecatedEdition, isDesktop } from '@/const/version';
9
+ import { isDesktop } from '@/const/version';
10
10
  import { getSearchConfig } from '@/helpers/getSearchConfig';
11
11
  import { createChatToolsEngine, createToolsEngine } from '@/helpers/toolEngineering';
12
12
  import { getAgentStoreState } from '@/store/agent';
@@ -38,7 +38,7 @@ import { createHeaderWithAuth } from '../_auth';
38
38
  import { API_ENDPOINTS } from '../_url';
39
39
  import { initializeWithClientStore } from './clientModelRuntime';
40
40
  import { contextEngineering } from './contextEngineering';
41
- import { findDeploymentName, isEnableFetchOnClient } from './helper';
41
+ import { findDeploymentName, isEnableFetchOnClient, resolveRuntimeProvider } from './helper';
42
42
  import { FetchOptions } from './types';
43
43
 
44
44
  interface GetChatCompletionPayload extends Partial<Omit<ChatStreamPayload, 'messages'>> {
@@ -268,6 +268,8 @@ class ChatService {
268
268
  { ...res, apiMode, model },
269
269
  );
270
270
 
271
+ const sdkType = resolveRuntimeProvider(provider);
272
+
271
273
  /**
272
274
  * Use browser agent runtime
273
275
  */
@@ -287,7 +289,7 @@ class ChatService {
287
289
  */
288
290
  fetcher = async () => {
289
291
  try {
290
- return await this.fetchOnClient({ payload, provider, signal });
292
+ return await this.fetchOnClient({ payload, provider, runtimeProvider: sdkType, signal });
291
293
  } catch (e) {
292
294
  const {
293
295
  errorType = ChatErrorType.BadRequest,
@@ -314,17 +316,6 @@ class ChatService {
314
316
  const { DEFAULT_MODEL_PROVIDER_LIST } = await import('@/config/modelProviders');
315
317
  const providerConfig = DEFAULT_MODEL_PROVIDER_LIST.find((item) => item.id === provider);
316
318
 
317
- let sdkType = provider;
318
- const isBuiltin = Object.values(ModelProvider).includes(provider as any);
319
-
320
- // TODO: remove `!isDeprecatedEdition` condition in V2.0
321
- if (!isDeprecatedEdition && !isBuiltin) {
322
- const providerConfig =
323
- aiProviderSelectors.providerConfigById(provider)(getAiInfraStoreState());
324
-
325
- sdkType = providerConfig?.settings.sdkType || 'openai';
326
- }
327
-
328
319
  const userPreferTransitionMode =
329
320
  userGeneralSettingsSelectors.transitionMode(getUserStoreState());
330
321
 
@@ -461,6 +452,7 @@ class ChatService {
461
452
  private fetchOnClient = async (params: {
462
453
  payload: Partial<ChatStreamPayload>;
463
454
  provider: string;
455
+ runtimeProvider: string;
464
456
  signal?: AbortSignal;
465
457
  }) => {
466
458
  /**
@@ -471,7 +463,11 @@ class ChatService {
471
463
  throw AgentRuntimeError.createError(ChatErrorType.InvalidAccessCode);
472
464
  }
473
465
 
474
- const agentRuntime = await initializeWithClientStore(params.provider, params.payload);
466
+ const agentRuntime = await initializeWithClientStore({
467
+ payload: params.payload,
468
+ provider: params.provider,
469
+ runtimeProvider: params.runtimeProvider,
470
+ });
475
471
  const data = params.payload as ChatStreamPayload;
476
472
 
477
473
  return agentRuntime.chat(data, { signal: params.signal });
@@ -8,6 +8,7 @@ import { getMessageError } from '@/utils/fetch';
8
8
 
9
9
  import { API_ENDPOINTS } from './_url';
10
10
  import { initializeWithClientStore } from './chat/clientModelRuntime';
11
+ import { resolveRuntimeProvider } from './chat/helper';
11
12
 
12
13
  const isEnableFetchOnClient = (provider: string) => {
13
14
  // TODO: remove this condition in V2.0
@@ -41,17 +42,22 @@ export class ModelsService {
41
42
  headers: { 'Content-Type': 'application/json' },
42
43
  provider,
43
44
  });
45
+
46
+ const runtimeProvider = resolveRuntimeProvider(provider);
44
47
  try {
45
48
  /**
46
49
  * Use browser agent runtime
47
50
  */
48
51
  const enableFetchOnClient = isEnableFetchOnClient(provider);
49
52
  if (enableFetchOnClient) {
50
- const agentRuntime = await initializeWithClientStore(provider);
53
+ const agentRuntime = await initializeWithClientStore({
54
+ provider,
55
+ runtimeProvider,
56
+ });
51
57
  return agentRuntime.models();
52
58
  }
53
59
 
54
- const res = await fetch(API_ENDPOINTS.models(provider), { headers });
60
+ const res = await fetch(API_ENDPOINTS.models(runtimeProvider), { headers });
55
61
  if (!res.ok) return;
56
62
 
57
63
  return res.json();
@@ -77,15 +83,19 @@ export class ModelsService {
77
83
  provider,
78
84
  });
79
85
 
86
+ const runtimeProvider = resolveRuntimeProvider(provider);
80
87
  const enableFetchOnClient = isEnableFetchOnClient(provider);
81
88
 
82
89
  console.log('enableFetchOnClient:', enableFetchOnClient);
83
90
  let res: Response;
84
91
  if (enableFetchOnClient) {
85
- const agentRuntime = await initializeWithClientStore(provider);
92
+ const agentRuntime = await initializeWithClientStore({
93
+ provider,
94
+ runtimeProvider,
95
+ });
86
96
  res = (await agentRuntime.pullModel({ model }, { signal }))!;
87
97
  } else {
88
- res = await fetch(API_ENDPOINTS.modelPull(provider), {
98
+ res = await fetch(API_ENDPOINTS.modelPull(runtimeProvider), {
89
99
  body: JSON.stringify({ model }),
90
100
  headers,
91
101
  method: 'POST',