@lobehub/chat 1.118.4 → 1.118.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.
- package/.github/workflows/test.yml +36 -1
- package/CHANGELOG.md +59 -0
- package/changelog/v1.json +18 -0
- package/locales/ar/setting.json +4 -0
- package/locales/bg-BG/setting.json +4 -0
- package/locales/de-DE/setting.json +4 -0
- package/locales/en-US/setting.json +4 -0
- package/locales/es-ES/setting.json +4 -0
- package/locales/fa-IR/setting.json +4 -0
- package/locales/fr-FR/setting.json +4 -0
- package/locales/it-IT/setting.json +4 -0
- package/locales/ja-JP/setting.json +4 -0
- package/locales/ko-KR/setting.json +4 -0
- package/locales/nl-NL/setting.json +4 -0
- package/locales/pl-PL/setting.json +4 -0
- package/locales/pt-BR/setting.json +4 -0
- package/locales/ru-RU/setting.json +4 -0
- package/locales/tr-TR/setting.json +4 -0
- package/locales/vi-VN/setting.json +4 -0
- package/locales/zh-CN/setting.json +4 -0
- package/locales/zh-TW/setting.json +4 -0
- package/package.json +2 -1
- package/packages/const/package.json +4 -1
- package/packages/const/src/image.ts +1 -1
- package/packages/const/src/settings/agent.ts +1 -0
- package/packages/database/src/repositories/aiInfra/index.ts +7 -2
- package/packages/model-bank/package.json +75 -0
- package/{src/config → packages/model-bank/src}/aiModels/bfl.ts +1 -1
- package/{src/config → packages/model-bank/src}/aiModels/fal.ts +1 -1
- package/{src/config → packages/model-bank/src}/aiModels/google.ts +1 -1
- package/{src/config → packages/model-bank/src}/aiModels/index.ts +2 -2
- package/{src/config → packages/model-bank/src}/aiModels/openai.ts +1 -1
- package/packages/model-bank/src/exports.test.ts +37 -0
- package/packages/model-bank/src/index.ts +2 -0
- package/{src/libs → packages/model-bank/src}/standard-parameters/index.ts +1 -1
- package/packages/model-bank/vitest.config.mts +11 -0
- package/packages/model-runtime/package.json +1 -0
- package/packages/model-runtime/src/ai360/index.ts +1 -1
- package/packages/model-runtime/src/aihubmix/index.ts +1 -1
- package/packages/model-runtime/src/anthropic/index.ts +6 -6
- package/packages/model-runtime/src/baichuan/index.ts +1 -1
- package/packages/model-runtime/src/bfl/createImage.ts +1 -2
- package/packages/model-runtime/src/cloudflare/index.ts +1 -1
- package/packages/model-runtime/src/cohere/index.ts +1 -1
- package/packages/model-runtime/src/deepseek/index.ts +1 -1
- package/packages/model-runtime/src/fal/index.ts +1 -2
- package/packages/model-runtime/src/fireworksai/index.ts +1 -1
- package/packages/model-runtime/src/groq/index.ts +1 -1
- package/packages/model-runtime/src/higress/index.ts +1 -1
- package/packages/model-runtime/src/huggingface/index.ts +1 -1
- package/packages/model-runtime/src/hunyuan/index.ts +1 -1
- package/packages/model-runtime/src/infiniai/index.ts +1 -1
- package/packages/model-runtime/src/internlm/index.ts +1 -1
- package/packages/model-runtime/src/jina/index.ts +1 -1
- package/packages/model-runtime/src/lmstudio/index.ts +1 -1
- package/packages/model-runtime/src/minimax/index.ts +1 -1
- package/packages/model-runtime/src/mistral/index.ts +1 -1
- package/packages/model-runtime/src/novita/__snapshots__/index.test.ts.snap +309 -21
- package/packages/model-runtime/src/novita/index.ts +31 -1
- package/packages/model-runtime/src/ollama/index.ts +1 -1
- package/packages/model-runtime/src/openai/__snapshots__/index.test.ts.snap +28 -0
- package/packages/model-runtime/src/openai/index.test.ts +0 -3
- package/packages/model-runtime/src/openrouter/__snapshots__/index.test.ts.snap +46 -0
- package/packages/model-runtime/src/openrouter/index.test.ts +21 -45
- package/packages/model-runtime/src/openrouter/index.ts +22 -25
- package/packages/model-runtime/src/openrouter/type.ts +12 -24
- package/packages/model-runtime/src/ppio/index.ts +1 -1
- package/packages/model-runtime/src/search1api/index.ts +1 -1
- package/packages/model-runtime/src/sensenova/index.ts +1 -1
- package/packages/model-runtime/src/stepfun/index.ts +1 -1
- package/packages/model-runtime/src/tencentcloud/index.ts +1 -1
- package/packages/model-runtime/src/togetherai/index.ts +1 -1
- package/packages/model-runtime/src/types/image.ts +1 -1
- package/packages/model-runtime/src/utils/modelParse.test.ts +5 -5
- package/packages/model-runtime/src/utils/modelParse.ts +47 -22
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/createImage.ts +1 -2
- package/packages/model-runtime/src/utils/openaiCompatibleFactory/index.ts +1 -1
- package/packages/model-runtime/src/vllm/index.ts +1 -1
- package/packages/model-runtime/src/xinference/index.ts +1 -1
- package/packages/types/src/agent/chatConfig.ts +6 -0
- package/packages/types/src/aiModel.ts +1 -2
- package/packages/types/src/llm.ts +1 -1
- package/packages/utils/src/getFallbackModelProperty.test.ts +1 -1
- package/packages/utils/src/getFallbackModelProperty.ts +1 -1
- package/packages/utils/src/parseModels.test.ts +1 -2
- package/packages/utils/src/parseModels.ts +1 -1
- package/src/app/[variants]/(main)/image/features/GenerationFeed/BatchItem.tsx +1 -1
- package/src/app/[variants]/(main)/profile/features/ClerkProfile.tsx +1 -1
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +1 -5
- package/src/features/AgentSetting/AgentModal/index.tsx +9 -0
- package/src/locales/default/models.ts +1 -1
- package/src/locales/default/setting.ts +4 -0
- package/src/server/globalConfig/genServerAiProviderConfig.test.ts +3 -3
- package/src/server/globalConfig/genServerAiProviderConfig.ts +1 -1
- package/src/server/routers/async/image.ts +1 -1
- package/src/server/services/discover/index.test.ts +1 -1
- package/src/server/services/discover/index.ts +16 -8
- package/src/services/chat.ts +8 -1
- package/src/store/agent/slices/chat/selectors/__snapshots__/agent.test.ts.snap +1 -0
- package/src/store/aiInfra/slices/aiProvider/action.ts +1 -1
- package/src/store/image/slices/generationConfig/action.test.ts +2 -6
- package/src/store/image/slices/generationConfig/action.ts +3 -3
- package/src/store/image/slices/generationConfig/hooks.test.ts +2 -2
- package/src/store/image/slices/generationConfig/hooks.ts +1 -1
- package/src/store/image/slices/generationConfig/initialState.ts +2 -3
- package/src/store/image/slices/generationConfig/selectors.test.ts +1 -2
- package/src/store/image/slices/generationConfig/selectors.ts +1 -1
- package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +2 -0
- /package/{src/config → packages/model-bank/src}/aiModels/ai21.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/ai302.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/ai360.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/aihubmix.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/akashchat.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/anthropic.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/azure.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/azureai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/baichuan.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/bedrock.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/cloudflare.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/cohere.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/deepseek.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/fireworksai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/giteeai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/github.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/groq.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/higress.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/huggingface.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/hunyuan.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/infiniai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/internlm.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/jina.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/lmstudio.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/lobehub.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/minimax.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/mistral.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/modelscope.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/moonshot.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/novita.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/nvidia.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/ollama.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/openrouter.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/perplexity.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/ppio.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/qiniu.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/qwen.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/sambanova.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/search1api.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/sensenova.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/siliconcloud.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/spark.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/stepfun.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/taichu.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/tencentcloud.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/togetherai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/upstage.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/v0.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/vertexai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/vllm.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/volcengine.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/wenxin.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/xai.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/xinference.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/zeroone.ts +0 -0
- /package/{src/config → packages/model-bank/src}/aiModels/zhipu.ts +0 -0
- /package/{src/libs → packages/model-bank/src}/standard-parameters/index.test.ts +0 -0
@@ -10,6 +10,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
10
10
|
"functionCall": false,
|
11
11
|
"id": "whisper-1",
|
12
12
|
"maxOutput": undefined,
|
13
|
+
"pricing": undefined,
|
13
14
|
"reasoning": false,
|
14
15
|
"releasedAt": "2023-02-27",
|
15
16
|
"type": "stt",
|
@@ -23,6 +24,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
23
24
|
"functionCall": false,
|
24
25
|
"id": "davinci-002",
|
25
26
|
"maxOutput": undefined,
|
27
|
+
"pricing": undefined,
|
26
28
|
"reasoning": false,
|
27
29
|
"releasedAt": "2023-08-21",
|
28
30
|
"type": "chat",
|
@@ -36,6 +38,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
36
38
|
"functionCall": true,
|
37
39
|
"id": "gpt-3.5-turbo",
|
38
40
|
"maxOutput": undefined,
|
41
|
+
"pricing": undefined,
|
39
42
|
"reasoning": false,
|
40
43
|
"releasedAt": "2023-02-28",
|
41
44
|
"type": "chat",
|
@@ -65,6 +68,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
65
68
|
],
|
66
69
|
},
|
67
70
|
},
|
71
|
+
"pricing": undefined,
|
68
72
|
"reasoning": false,
|
69
73
|
"releasedAt": "2023-11-01",
|
70
74
|
"type": "image",
|
@@ -78,6 +82,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
78
82
|
"functionCall": false,
|
79
83
|
"id": "gpt-3.5-turbo-16k",
|
80
84
|
"maxOutput": undefined,
|
85
|
+
"pricing": undefined,
|
81
86
|
"reasoning": false,
|
82
87
|
"releasedAt": "2023-05-10",
|
83
88
|
"type": "chat",
|
@@ -91,6 +96,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
91
96
|
"functionCall": false,
|
92
97
|
"id": "tts-1-hd-1106",
|
93
98
|
"maxOutput": undefined,
|
99
|
+
"pricing": undefined,
|
94
100
|
"reasoning": false,
|
95
101
|
"releasedAt": "2023-11-03",
|
96
102
|
"type": "chat",
|
@@ -104,6 +110,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
104
110
|
"functionCall": false,
|
105
111
|
"id": "tts-1-hd",
|
106
112
|
"maxOutput": undefined,
|
113
|
+
"pricing": undefined,
|
107
114
|
"reasoning": false,
|
108
115
|
"releasedAt": "2023-11-03",
|
109
116
|
"type": "tts",
|
@@ -117,6 +124,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
117
124
|
"functionCall": false,
|
118
125
|
"id": "gpt-3.5-turbo-16k-0613",
|
119
126
|
"maxOutput": undefined,
|
127
|
+
"pricing": undefined,
|
120
128
|
"reasoning": false,
|
121
129
|
"releasedAt": "2023-05-30",
|
122
130
|
"type": "chat",
|
@@ -130,6 +138,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
130
138
|
"functionCall": false,
|
131
139
|
"id": "text-embedding-3-large",
|
132
140
|
"maxOutput": undefined,
|
141
|
+
"pricing": undefined,
|
133
142
|
"reasoning": false,
|
134
143
|
"releasedAt": "2024-01-22",
|
135
144
|
"type": "embedding",
|
@@ -143,6 +152,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
143
152
|
"functionCall": false,
|
144
153
|
"id": "gpt-4-1106-vision-preview",
|
145
154
|
"maxOutput": undefined,
|
155
|
+
"pricing": undefined,
|
146
156
|
"reasoning": false,
|
147
157
|
"releasedAt": "2024-03-26",
|
148
158
|
"type": "chat",
|
@@ -156,6 +166,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
156
166
|
"functionCall": false,
|
157
167
|
"id": "gpt-3.5-turbo-instruct-0914",
|
158
168
|
"maxOutput": undefined,
|
169
|
+
"pricing": undefined,
|
159
170
|
"reasoning": false,
|
160
171
|
"releasedAt": "2023-09-07",
|
161
172
|
"type": "chat",
|
@@ -169,6 +180,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
169
180
|
"functionCall": true,
|
170
181
|
"id": "gpt-4-0125-preview",
|
171
182
|
"maxOutput": undefined,
|
183
|
+
"pricing": undefined,
|
172
184
|
"reasoning": false,
|
173
185
|
"releasedAt": "2024-01-23",
|
174
186
|
"type": "chat",
|
@@ -182,6 +194,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
182
194
|
"functionCall": true,
|
183
195
|
"id": "gpt-4-turbo-preview",
|
184
196
|
"maxOutput": undefined,
|
197
|
+
"pricing": undefined,
|
185
198
|
"reasoning": false,
|
186
199
|
"releasedAt": "2024-01-23",
|
187
200
|
"type": "chat",
|
@@ -195,6 +208,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
195
208
|
"functionCall": false,
|
196
209
|
"id": "gpt-3.5-turbo-instruct",
|
197
210
|
"maxOutput": undefined,
|
211
|
+
"pricing": undefined,
|
198
212
|
"reasoning": false,
|
199
213
|
"releasedAt": "2023-08-24",
|
200
214
|
"type": "chat",
|
@@ -208,6 +222,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
208
222
|
"functionCall": false,
|
209
223
|
"id": "gpt-3.5-turbo-0301",
|
210
224
|
"maxOutput": undefined,
|
225
|
+
"pricing": undefined,
|
211
226
|
"reasoning": false,
|
212
227
|
"releasedAt": "2023-03-01",
|
213
228
|
"type": "chat",
|
@@ -221,6 +236,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
221
236
|
"functionCall": false,
|
222
237
|
"id": "gpt-3.5-turbo-0613",
|
223
238
|
"maxOutput": undefined,
|
239
|
+
"pricing": undefined,
|
224
240
|
"reasoning": false,
|
225
241
|
"releasedAt": "2023-06-12",
|
226
242
|
"type": "chat",
|
@@ -234,6 +250,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
234
250
|
"functionCall": false,
|
235
251
|
"id": "tts-1",
|
236
252
|
"maxOutput": undefined,
|
253
|
+
"pricing": undefined,
|
237
254
|
"reasoning": false,
|
238
255
|
"releasedAt": "2023-04-19",
|
239
256
|
"type": "tts",
|
@@ -260,6 +277,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
260
277
|
],
|
261
278
|
},
|
262
279
|
},
|
280
|
+
"pricing": undefined,
|
263
281
|
"reasoning": false,
|
264
282
|
"releasedAt": "2023-10-31",
|
265
283
|
"type": "image",
|
@@ -273,6 +291,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
273
291
|
"functionCall": true,
|
274
292
|
"id": "gpt-3.5-turbo-1106",
|
275
293
|
"maxOutput": undefined,
|
294
|
+
"pricing": undefined,
|
276
295
|
"reasoning": false,
|
277
296
|
"releasedAt": "2023-11-02",
|
278
297
|
"type": "chat",
|
@@ -286,6 +305,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
286
305
|
"functionCall": true,
|
287
306
|
"id": "gpt-4-1106-preview",
|
288
307
|
"maxOutput": undefined,
|
308
|
+
"pricing": undefined,
|
289
309
|
"reasoning": false,
|
290
310
|
"releasedAt": "2023-11-02",
|
291
311
|
"type": "chat",
|
@@ -299,6 +319,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
299
319
|
"functionCall": false,
|
300
320
|
"id": "babbage-002",
|
301
321
|
"maxOutput": undefined,
|
322
|
+
"pricing": undefined,
|
302
323
|
"reasoning": false,
|
303
324
|
"releasedAt": "2023-08-21",
|
304
325
|
"type": "chat",
|
@@ -312,6 +333,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
312
333
|
"functionCall": false,
|
313
334
|
"id": "tts-1-1106",
|
314
335
|
"maxOutput": undefined,
|
336
|
+
"pricing": undefined,
|
315
337
|
"reasoning": false,
|
316
338
|
"releasedAt": "2023-11-03",
|
317
339
|
"type": "chat",
|
@@ -325,6 +347,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
325
347
|
"functionCall": false,
|
326
348
|
"id": "gpt-4-vision-preview",
|
327
349
|
"maxOutput": undefined,
|
350
|
+
"pricing": undefined,
|
328
351
|
"reasoning": false,
|
329
352
|
"releasedAt": "2023-11-02",
|
330
353
|
"type": "chat",
|
@@ -338,6 +361,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
338
361
|
"functionCall": false,
|
339
362
|
"id": "text-embedding-3-small",
|
340
363
|
"maxOutput": undefined,
|
364
|
+
"pricing": undefined,
|
341
365
|
"reasoning": false,
|
342
366
|
"releasedAt": "2024-01-22",
|
343
367
|
"type": "embedding",
|
@@ -351,6 +375,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
351
375
|
"functionCall": true,
|
352
376
|
"id": "gpt-4",
|
353
377
|
"maxOutput": undefined,
|
378
|
+
"pricing": undefined,
|
354
379
|
"reasoning": false,
|
355
380
|
"releasedAt": "2023-06-27",
|
356
381
|
"type": "chat",
|
@@ -364,6 +389,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
364
389
|
"functionCall": false,
|
365
390
|
"id": "text-embedding-ada-002",
|
366
391
|
"maxOutput": undefined,
|
392
|
+
"pricing": undefined,
|
367
393
|
"reasoning": false,
|
368
394
|
"releasedAt": "2022-12-16",
|
369
395
|
"type": "embedding",
|
@@ -377,6 +403,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
377
403
|
"functionCall": true,
|
378
404
|
"id": "gpt-3.5-turbo-0125",
|
379
405
|
"maxOutput": undefined,
|
406
|
+
"pricing": undefined,
|
380
407
|
"reasoning": false,
|
381
408
|
"releasedAt": "2024-01-23",
|
382
409
|
"type": "chat",
|
@@ -390,6 +417,7 @@ exports[`LobeOpenAI > models > should get models 1`] = `
|
|
390
417
|
"functionCall": true,
|
391
418
|
"id": "gpt-4-0613",
|
392
419
|
"maxOutput": undefined,
|
420
|
+
"pricing": undefined,
|
393
421
|
"reasoning": false,
|
394
422
|
"releasedAt": "2023-06-12",
|
395
423
|
"type": "chat",
|
@@ -2,9 +2,6 @@
|
|
2
2
|
import OpenAI from 'openai';
|
3
3
|
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
4
4
|
|
5
|
-
// 引入模块以便于对函数进行spy
|
6
|
-
import { ChatStreamCallbacks } from '@/libs/model-runtime';
|
7
|
-
|
8
5
|
import * as debugStreamModule from '../utils/debugStream';
|
9
6
|
import officalOpenAIModels from './fixtures/openai-models.json';
|
10
7
|
import { LobeOpenAI } from './index';
|
@@ -1,5 +1,51 @@
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
2
2
|
|
3
|
+
exports[`LobeOpenRouterAI > chat > should handle fetch error gracefully 1`] = `
|
4
|
+
[
|
5
|
+
{
|
6
|
+
"contextWindowTokens": 131072,
|
7
|
+
"description": "Reflection Llama-3.1 70B is trained with a new technique called Reflection-Tuning that teaches a LLM to detect mistakes in its reasoning and correct course.
|
8
|
+
|
9
|
+
The model was trained on synthetic data.
|
10
|
+
|
11
|
+
_These are free, rate-limited endpoints for [Reflection 70B](/models/mattshumer/reflection-70b). Outputs may be cached. Read about rate limits [here](/docs/limits)._",
|
12
|
+
"displayName": "Reflection 70B",
|
13
|
+
"enabled": false,
|
14
|
+
"functionCall": false,
|
15
|
+
"id": "mattshumer/reflection-70b:free",
|
16
|
+
"maxOutput": undefined,
|
17
|
+
"pricing": undefined,
|
18
|
+
"reasoning": false,
|
19
|
+
"releasedAt": "1970-01-20",
|
20
|
+
"type": "chat",
|
21
|
+
"vision": false,
|
22
|
+
},
|
23
|
+
]
|
24
|
+
`;
|
25
|
+
|
26
|
+
exports[`LobeOpenRouterAI > chat > should handle fetch failure gracefully 1`] = `
|
27
|
+
[
|
28
|
+
{
|
29
|
+
"contextWindowTokens": 131072,
|
30
|
+
"description": "Reflection Llama-3.1 70B is trained with a new technique called Reflection-Tuning that teaches a LLM to detect mistakes in its reasoning and correct course.
|
31
|
+
|
32
|
+
The model was trained on synthetic data.
|
33
|
+
|
34
|
+
_These are free, rate-limited endpoints for [Reflection 70B](/models/mattshumer/reflection-70b). Outputs may be cached. Read about rate limits [here](/docs/limits)._",
|
35
|
+
"displayName": "Reflection 70B",
|
36
|
+
"enabled": false,
|
37
|
+
"functionCall": false,
|
38
|
+
"id": "mattshumer/reflection-70b:free",
|
39
|
+
"maxOutput": undefined,
|
40
|
+
"pricing": undefined,
|
41
|
+
"reasoning": false,
|
42
|
+
"releasedAt": "1970-01-20",
|
43
|
+
"type": "chat",
|
44
|
+
"vision": false,
|
45
|
+
},
|
46
|
+
]
|
47
|
+
`;
|
48
|
+
|
3
49
|
exports[`LobeOpenRouterAI > models > should get models with frontend models data 1`] = `
|
4
50
|
[
|
5
51
|
{
|
@@ -4,7 +4,6 @@ import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
4
|
import { LobeOpenAICompatibleRuntime } from '@/libs/model-runtime';
|
5
5
|
import { testProvider } from '@/libs/model-runtime/providerTestUtils';
|
6
6
|
|
7
|
-
import frontendModels from './fixtures/frontendModels.json';
|
8
7
|
import models from './fixtures/models.json';
|
9
8
|
import { LobeOpenRouterAI } from './index';
|
10
9
|
|
@@ -30,11 +29,17 @@ let instance: LobeOpenAICompatibleRuntime;
|
|
30
29
|
beforeEach(() => {
|
31
30
|
instance = new LobeOpenRouterAI({ apiKey: 'test' });
|
32
31
|
|
33
|
-
//
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
// 用一个完整的假 client 覆盖实例的 client,避免访问深层属性时出现初始化顺序问题
|
33
|
+
instance['client'] = {
|
34
|
+
chat: {
|
35
|
+
completions: {
|
36
|
+
create: vi.fn().mockResolvedValue(Promise.resolve(new ReadableStream())),
|
37
|
+
},
|
38
|
+
},
|
39
|
+
models: {
|
40
|
+
list: vi.fn().mockResolvedValue({ data: [] }),
|
41
|
+
},
|
42
|
+
} as any;
|
38
43
|
});
|
39
44
|
|
40
45
|
afterEach(() => {
|
@@ -44,12 +49,12 @@ afterEach(() => {
|
|
44
49
|
describe('LobeOpenRouterAI', () => {
|
45
50
|
describe('init', () => {
|
46
51
|
it('should correctly initialize with a custom base URL', async () => {
|
47
|
-
const
|
52
|
+
const inst = new LobeOpenRouterAI({
|
48
53
|
apiKey: 'test_api_key',
|
49
54
|
baseURL: 'https://api.abc.com/v1',
|
50
55
|
});
|
51
|
-
expect(
|
52
|
-
expect(
|
56
|
+
expect(inst).toBeInstanceOf(LobeOpenRouterAI);
|
57
|
+
expect(inst.baseURL).toEqual('https://api.abc.com/v1');
|
53
58
|
});
|
54
59
|
});
|
55
60
|
|
@@ -135,35 +140,6 @@ describe('LobeOpenRouterAI', () => {
|
|
135
140
|
);
|
136
141
|
expect(result).toBeInstanceOf(Response);
|
137
142
|
});
|
138
|
-
});
|
139
|
-
|
140
|
-
describe('models', () => {
|
141
|
-
it('should get models with frontend models data', async () => {
|
142
|
-
// mock the models.list method
|
143
|
-
(instance['client'].models.list as Mock).mockResolvedValue({ data: models });
|
144
|
-
|
145
|
-
// 模拟成功的 fetch 响应
|
146
|
-
vi.stubGlobal(
|
147
|
-
'fetch',
|
148
|
-
vi.fn().mockResolvedValue({
|
149
|
-
ok: true,
|
150
|
-
json: vi.fn().mockResolvedValue(frontendModels),
|
151
|
-
}),
|
152
|
-
);
|
153
|
-
|
154
|
-
const list = await instance.models();
|
155
|
-
|
156
|
-
// 验证 fetch 被正确调用
|
157
|
-
expect(fetch).toHaveBeenCalledWith('https://openrouter.ai/api/frontend/models');
|
158
|
-
|
159
|
-
// 验证模型列表中包含了从前端 API 获取的额外信息
|
160
|
-
const reflectionModel = list.find((model) => model.id === 'mattshumer/reflection-70b:free');
|
161
|
-
expect(reflectionModel).toBeDefined();
|
162
|
-
expect(reflectionModel?.reasoning).toBe(true);
|
163
|
-
expect(reflectionModel?.functionCall).toBe(true);
|
164
|
-
|
165
|
-
expect(list).toMatchSnapshot();
|
166
|
-
});
|
167
143
|
|
168
144
|
it('should handle fetch failure gracefully', async () => {
|
169
145
|
// mock the models.list method
|
@@ -179,10 +155,10 @@ describe('LobeOpenRouterAI', () => {
|
|
179
155
|
|
180
156
|
const list = await instance.models();
|
181
157
|
|
182
|
-
//
|
158
|
+
// 验证在当前实现中,当 frontend fetch 返回非 ok 时,会返回空列表
|
183
159
|
expect(fetch).toHaveBeenCalledWith('https://openrouter.ai/api/frontend/models');
|
184
|
-
expect(list.length).
|
185
|
-
expect(list).
|
160
|
+
expect(list.length).toBe(0);
|
161
|
+
expect(list).toEqual([]);
|
186
162
|
});
|
187
163
|
|
188
164
|
it('should handle fetch error gracefully', async () => {
|
@@ -190,15 +166,15 @@ describe('LobeOpenRouterAI', () => {
|
|
190
166
|
(instance['client'].models.list as Mock).mockResolvedValue({ data: models });
|
191
167
|
|
192
168
|
// 在测试环境中,需要先修改 fetch 的实现,确保错误被捕获
|
193
|
-
vi.spyOn(
|
169
|
+
vi.spyOn(globalThis, 'fetch').mockImplementation(() => {
|
194
170
|
throw new Error('Network error');
|
195
171
|
});
|
196
172
|
|
197
173
|
const list = await instance.models();
|
198
174
|
|
199
|
-
//
|
200
|
-
expect(list.length).
|
201
|
-
expect(list).
|
175
|
+
// 验证在当前实现中,当 frontend fetch 抛错时,会返回空列表
|
176
|
+
expect(list.length).toBe(0);
|
177
|
+
expect(list).toEqual([]);
|
202
178
|
});
|
203
179
|
});
|
204
180
|
});
|
@@ -1,9 +1,9 @@
|
|
1
|
-
import OpenRouterModels from '
|
1
|
+
import { openrouter as OpenRouterModels } from 'model-bank';
|
2
2
|
|
3
3
|
import { ModelProvider } from '../types';
|
4
4
|
import { processMultiProviderModelList } from '../utils/modelParse';
|
5
5
|
import { createOpenAICompatibleRuntime } from '../utils/openaiCompatibleFactory';
|
6
|
-
import { OpenRouterModelCard,
|
6
|
+
import { OpenRouterModelCard, OpenRouterReasoning } from './type';
|
7
7
|
|
8
8
|
const formatPrice = (price: string) => {
|
9
9
|
if (price === '-1') return undefined;
|
@@ -55,48 +55,45 @@ export const LobeOpenRouterAI = createOpenAICompatibleRuntime({
|
|
55
55
|
debug: {
|
56
56
|
chatCompletion: () => process.env.DEBUG_OPENROUTER_CHAT_COMPLETION === '1',
|
57
57
|
},
|
58
|
-
models: async (
|
59
|
-
|
60
|
-
const modelList: OpenRouterModelCard[] = modelsPage.data;
|
58
|
+
models: async () => {
|
59
|
+
let modelList: OpenRouterModelCard[] = [];
|
61
60
|
|
62
|
-
const modelsExtraInfo: OpenRouterModelExtraInfo[] = [];
|
63
61
|
try {
|
64
62
|
const response = await fetch('https://openrouter.ai/api/frontend/models');
|
65
63
|
if (response.ok) {
|
66
64
|
const data = await response.json();
|
67
|
-
|
65
|
+
modelList = data['data'];
|
68
66
|
}
|
69
67
|
} catch (error) {
|
70
68
|
console.error('Failed to fetch OpenRouter frontend models:', error);
|
69
|
+
return [];
|
71
70
|
}
|
72
71
|
|
73
|
-
//
|
72
|
+
// 处理前端获取的模型信息,转换为标准格式
|
74
73
|
const formattedModels = modelList.map((model) => {
|
75
|
-
const
|
76
|
-
(
|
77
|
-
|
74
|
+
const displayName = model.slug?.toLowerCase().includes('deepseek')
|
75
|
+
? (model.name ?? model.slug)
|
76
|
+
: (model.short_name ?? model.name ?? model.slug);
|
78
77
|
|
79
78
|
return {
|
80
79
|
contextWindowTokens: model.context_length,
|
81
80
|
description: model.description,
|
82
|
-
displayName
|
83
|
-
functionCall:
|
84
|
-
|
85
|
-
model.description.includes('tools') ||
|
86
|
-
extraInfo?.endpoint?.supports_tool_parameters ||
|
87
|
-
false,
|
88
|
-
id: model.id,
|
81
|
+
displayName,
|
82
|
+
functionCall: model.endpoint?.supports_tool_parameters || false,
|
83
|
+
id: model.slug,
|
89
84
|
maxOutput:
|
90
|
-
typeof model.
|
91
|
-
? model.
|
85
|
+
typeof model.endpoint?.max_completion_tokens === 'number'
|
86
|
+
? model.endpoint.max_completion_tokens
|
92
87
|
: undefined,
|
93
88
|
pricing: {
|
94
|
-
input: formatPrice(model.pricing
|
95
|
-
output: formatPrice(model.pricing
|
89
|
+
input: formatPrice(model.endpoint?.pricing?.prompt),
|
90
|
+
output: formatPrice(model.endpoint?.pricing?.completion),
|
96
91
|
},
|
97
|
-
reasoning:
|
98
|
-
releasedAt: new Date(model.
|
99
|
-
vision:
|
92
|
+
reasoning: model.endpoint?.supports_reasoning || false,
|
93
|
+
releasedAt: new Date(model.created_at).toISOString().split('T')[0],
|
94
|
+
vision:
|
95
|
+
(Array.isArray(model.input_modalities) && model.input_modalities.includes('image')) ||
|
96
|
+
false,
|
100
97
|
};
|
101
98
|
});
|
102
99
|
|
@@ -5,39 +5,27 @@ interface ModelPricing {
|
|
5
5
|
request: string;
|
6
6
|
}
|
7
7
|
|
8
|
-
interface ModelArchitecture {
|
9
|
-
instruct_type: string | null;
|
10
|
-
modality: string;
|
11
|
-
tokenizer: string;
|
12
|
-
}
|
13
|
-
|
14
|
-
interface ModelTopProvider {
|
15
|
-
is_moderated: boolean;
|
16
|
-
max_completion_tokens: number | null;
|
17
|
-
}
|
18
|
-
|
19
8
|
export interface OpenRouterModelCard {
|
20
|
-
architecture: ModelArchitecture;
|
21
9
|
context_length: number;
|
22
|
-
|
23
|
-
description
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
10
|
+
created_at: number;
|
11
|
+
description?: string;
|
12
|
+
endpoint: OpenRouterModelEndpoint;
|
13
|
+
input_modalities?: string[];
|
14
|
+
name?: string;
|
15
|
+
output_modalities?: string[];
|
16
|
+
per_request_limits?: any | null;
|
17
|
+
short_name?: string;
|
18
|
+
slug: string;
|
29
19
|
}
|
30
20
|
|
31
21
|
interface OpenRouterModelEndpoint {
|
22
|
+
max_completion_tokens: number | null;
|
23
|
+
pricing: ModelPricing;
|
24
|
+
supported_parameters: string[];
|
32
25
|
supports_reasoning?: boolean;
|
33
26
|
supports_tool_parameters?: boolean;
|
34
27
|
}
|
35
28
|
|
36
|
-
export interface OpenRouterModelExtraInfo {
|
37
|
-
endpoint?: OpenRouterModelEndpoint;
|
38
|
-
slug: string;
|
39
|
-
}
|
40
|
-
|
41
29
|
interface OpenRouterOpenAIReasoning {
|
42
30
|
effort: 'high' | 'medium' | 'low';
|
43
31
|
exclude?: boolean;
|
@@ -15,7 +15,7 @@ export const LobePPIOAI = createOpenAICompatibleRuntime({
|
|
15
15
|
chatCompletion: () => process.env.DEBUG_PPIO_CHAT_COMPLETION === '1',
|
16
16
|
},
|
17
17
|
models: async ({ client }) => {
|
18
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('
|
18
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
|
19
19
|
|
20
20
|
const reasoningKeywords = ['deepseek-r1'];
|
21
21
|
|
@@ -37,7 +37,7 @@ export const LobeSearch1API = createOpenAICompatibleRuntime({
|
|
37
37
|
chatCompletion: () => process.env.DEBUG_SEARCH1API_CHAT_COMPLETION === '1',
|
38
38
|
},
|
39
39
|
models: async ({ client }) => {
|
40
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('
|
40
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
|
41
41
|
|
42
42
|
const modelsPage = (await client.models.list()) as any;
|
43
43
|
const modelList: Search1APIModelCard[] = modelsPage.data;
|
@@ -54,7 +54,7 @@ export const LobeSenseNovaAI = createOpenAICompatibleRuntime({
|
|
54
54
|
chatCompletion: () => process.env.DEBUG_SENSENOVA_CHAT_COMPLETION === '1',
|
55
55
|
},
|
56
56
|
models: async ({ client }) => {
|
57
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('
|
57
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
|
58
58
|
|
59
59
|
const functionCallKeywords = ['1202'];
|
60
60
|
|
@@ -36,7 +36,7 @@ export const LobeStepfunAI = createOpenAICompatibleRuntime({
|
|
36
36
|
chatCompletion: () => process.env.DEBUG_STEPFUN_CHAT_COMPLETION === '1',
|
37
37
|
},
|
38
38
|
models: async ({ client }) => {
|
39
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('
|
39
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
|
40
40
|
|
41
41
|
// ref: https://platform.stepfun.com/docs/llm/modeloverview
|
42
42
|
const functionCallKeywords = ['step-1-', 'step-1o-', 'step-1v-', 'step-2-'];
|
@@ -13,7 +13,7 @@ export const LobeTencentCloudAI = createOpenAICompatibleRuntime({
|
|
13
13
|
chatCompletion: () => process.env.DEBUG_TENCENT_CLOUD_CHAT_COMPLETION === '1',
|
14
14
|
},
|
15
15
|
models: async ({ client }) => {
|
16
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('
|
16
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
|
17
17
|
|
18
18
|
const reasoningKeywords = ['deepseek-r1'];
|
19
19
|
|
@@ -16,7 +16,7 @@ export const LobeTogetherAI = createOpenAICompatibleRuntime({
|
|
16
16
|
chatCompletion: () => process.env.DEBUG_TOGETHERAI_CHAT_COMPLETION === '1',
|
17
17
|
},
|
18
18
|
models: async ({ client }) => {
|
19
|
-
const { LOBE_DEFAULT_MODEL_LIST } = await import('
|
19
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('model-bank');
|
20
20
|
|
21
21
|
const visionKeywords = ['qvq', 'vision'];
|
22
22
|
|
@@ -98,7 +98,7 @@ const mockDefaultModelList: (Partial<ChatModelCard> & { id: string })[] = [
|
|
98
98
|
];
|
99
99
|
|
100
100
|
// Mock the import
|
101
|
-
vi.mock('
|
101
|
+
vi.mock('model-bank', () => ({
|
102
102
|
LOBE_DEFAULT_MODEL_LIST: mockDefaultModelList,
|
103
103
|
}));
|
104
104
|
|
@@ -394,7 +394,7 @@ describe('modelParse', () => {
|
|
394
394
|
reasoning: true,
|
395
395
|
},
|
396
396
|
};
|
397
|
-
const mockModule = await import('
|
397
|
+
const mockModule = await import('model-bank');
|
398
398
|
mockModule.LOBE_DEFAULT_MODEL_LIST.push(tempMockEntry as any);
|
399
399
|
|
400
400
|
const modelList = [{ id: modelId }];
|
@@ -481,7 +481,7 @@ describe('modelParse', () => {
|
|
481
481
|
contextWindowTokens: 5000,
|
482
482
|
};
|
483
483
|
|
484
|
-
const mockModule = await import('
|
484
|
+
const mockModule = await import('model-bank');
|
485
485
|
mockModule.LOBE_DEFAULT_MODEL_LIST.push(tempModelEntry as any);
|
486
486
|
|
487
487
|
const config = MODEL_LIST_CONFIGS.openai;
|
@@ -706,7 +706,7 @@ describe('modelParse', () => {
|
|
706
706
|
reasoning: true,
|
707
707
|
},
|
708
708
|
};
|
709
|
-
const mockModule = await import('
|
709
|
+
const mockModule = await import('model-bank');
|
710
710
|
mockModule.LOBE_DEFAULT_MODEL_LIST.push(tempMockEntry as any);
|
711
711
|
|
712
712
|
const modelList = [{ id: modelId }];
|
@@ -735,7 +735,7 @@ describe('modelParse', () => {
|
|
735
735
|
reasoning: false,
|
736
736
|
},
|
737
737
|
};
|
738
|
-
const mockModule = await import('
|
738
|
+
const mockModule = await import('model-bank');
|
739
739
|
mockModule.LOBE_DEFAULT_MODEL_LIST.push(tempMockEntry as any);
|
740
740
|
|
741
741
|
const modelList = [{ id: modelId }];
|