@lobehub/chat 1.136.13 → 1.137.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/.cursor/rules/add-setting-env.mdc +175 -0
  2. package/.cursor/rules/db-migrations.mdc +25 -0
  3. package/.env.example +7 -0
  4. package/CHANGELOG.md +50 -0
  5. package/Dockerfile +3 -2
  6. package/Dockerfile.database +15 -3
  7. package/Dockerfile.pglite +3 -2
  8. package/changelog/v1.json +18 -0
  9. package/docs/development/database-schema.dbml +1 -0
  10. package/docs/self-hosting/advanced/feature-flags.mdx +25 -15
  11. package/docs/self-hosting/advanced/feature-flags.zh-CN.mdx +25 -15
  12. package/docs/self-hosting/environment-variables/basic.mdx +12 -0
  13. package/docs/self-hosting/environment-variables/basic.zh-CN.mdx +12 -0
  14. package/locales/ar/setting.json +8 -0
  15. package/locales/bg-BG/setting.json +8 -0
  16. package/locales/de-DE/setting.json +8 -0
  17. package/locales/en-US/setting.json +8 -0
  18. package/locales/es-ES/setting.json +8 -0
  19. package/locales/fa-IR/setting.json +8 -0
  20. package/locales/fr-FR/setting.json +8 -0
  21. package/locales/it-IT/setting.json +8 -0
  22. package/locales/ja-JP/setting.json +8 -0
  23. package/locales/ko-KR/setting.json +8 -0
  24. package/locales/nl-NL/setting.json +8 -0
  25. package/locales/pl-PL/setting.json +8 -0
  26. package/locales/pt-BR/setting.json +8 -0
  27. package/locales/ru-RU/setting.json +8 -0
  28. package/locales/tr-TR/setting.json +8 -0
  29. package/locales/vi-VN/setting.json +8 -0
  30. package/locales/zh-CN/setting.json +8 -0
  31. package/locales/zh-TW/setting.json +8 -0
  32. package/package.json +1 -1
  33. package/packages/agent-runtime/examples/tools-calling.ts +4 -3
  34. package/packages/agent-runtime/src/core/__tests__/runtime.test.ts +559 -29
  35. package/packages/agent-runtime/src/core/runtime.ts +171 -43
  36. package/packages/agent-runtime/src/types/instruction.ts +32 -6
  37. package/packages/agent-runtime/src/types/runtime.ts +2 -2
  38. package/packages/agent-runtime/src/types/state.ts +1 -8
  39. package/packages/agent-runtime/vitest.config.mts +14 -0
  40. package/packages/const/src/settings/image.ts +8 -0
  41. package/packages/const/src/settings/index.ts +3 -0
  42. package/packages/context-engine/src/__tests__/pipeline.test.ts +485 -0
  43. package/packages/context-engine/src/base/__tests__/BaseProcessor.test.ts +381 -0
  44. package/packages/context-engine/src/base/__tests__/BaseProvider.test.ts +392 -0
  45. package/packages/context-engine/src/processors/__tests__/MessageCleanup.test.ts +346 -0
  46. package/packages/context-engine/src/processors/__tests__/ToolCall.test.ts +552 -0
  47. package/packages/database/migrations/0038_add_image_user_settings.sql +1 -0
  48. package/packages/database/migrations/meta/0038_snapshot.json +7580 -0
  49. package/packages/database/migrations/meta/_journal.json +7 -0
  50. package/packages/database/src/core/migrations.json +6 -0
  51. package/packages/database/src/models/user.ts +3 -1
  52. package/packages/database/src/schemas/user.ts +1 -0
  53. package/packages/file-loaders/src/loaders/docx/index.test.ts +0 -1
  54. package/packages/file-loaders/src/loaders/excel/__snapshots__/index.test.ts.snap +30 -0
  55. package/packages/file-loaders/src/loaders/excel/index.test.ts +8 -0
  56. package/packages/file-loaders/src/loaders/pptx/index.test.ts +25 -0
  57. package/packages/file-loaders/src/utils/parser-utils.test.ts +155 -0
  58. package/packages/file-loaders/vitest.config.mts +8 -0
  59. package/packages/model-runtime/CLAUDE.md +5 -0
  60. package/packages/model-runtime/docs/test-coverage.md +706 -0
  61. package/packages/model-runtime/src/core/ModelRuntime.test.ts +231 -0
  62. package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +1 -1
  63. package/packages/model-runtime/src/core/openaiCompatibleFactory/createImage.test.ts +799 -0
  64. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.test.ts +188 -4
  65. package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +41 -10
  66. package/packages/model-runtime/src/core/streams/openai/__snapshots__/responsesStream.test.ts.snap +439 -0
  67. package/packages/model-runtime/src/core/streams/openai/openai.test.ts +789 -0
  68. package/packages/model-runtime/src/core/streams/openai/responsesStream.test.ts +551 -0
  69. package/packages/model-runtime/src/core/usageConverters/utils/computeChatCost.test.ts +230 -0
  70. package/packages/model-runtime/src/core/usageConverters/utils/computeImageCost.test.ts +334 -37
  71. package/packages/model-runtime/src/providerTestUtils.ts +148 -145
  72. package/packages/model-runtime/src/providers/ai302/index.test.ts +60 -0
  73. package/packages/model-runtime/src/providers/ai302/index.ts +9 -4
  74. package/packages/model-runtime/src/providers/ai360/index.test.ts +1213 -1
  75. package/packages/model-runtime/src/providers/ai360/index.ts +9 -4
  76. package/packages/model-runtime/src/providers/aihubmix/index.test.ts +73 -0
  77. package/packages/model-runtime/src/providers/aihubmix/index.ts +6 -9
  78. package/packages/model-runtime/src/providers/akashchat/index.test.ts +433 -3
  79. package/packages/model-runtime/src/providers/akashchat/index.ts +12 -7
  80. package/packages/model-runtime/src/providers/anthropic/generateObject.test.ts +183 -29
  81. package/packages/model-runtime/src/providers/anthropic/generateObject.ts +40 -24
  82. package/packages/model-runtime/src/providers/azureai/index.test.ts +102 -0
  83. package/packages/model-runtime/src/providers/baichuan/index.test.ts +416 -26
  84. package/packages/model-runtime/src/providers/baichuan/index.ts +23 -20
  85. package/packages/model-runtime/src/providers/bedrock/index.test.ts +420 -2
  86. package/packages/model-runtime/src/providers/cerebras/index.test.ts +465 -0
  87. package/packages/model-runtime/src/providers/cerebras/index.ts +8 -3
  88. package/packages/model-runtime/src/providers/cohere/index.test.ts +1074 -1
  89. package/packages/model-runtime/src/providers/cohere/index.ts +8 -3
  90. package/packages/model-runtime/src/providers/cometapi/index.test.ts +439 -3
  91. package/packages/model-runtime/src/providers/cometapi/index.ts +8 -3
  92. package/packages/model-runtime/src/providers/deepseek/index.test.ts +116 -1
  93. package/packages/model-runtime/src/providers/deepseek/index.ts +8 -3
  94. package/packages/model-runtime/src/providers/fireworksai/index.test.ts +264 -3
  95. package/packages/model-runtime/src/providers/fireworksai/index.ts +8 -3
  96. package/packages/model-runtime/src/providers/giteeai/index.test.ts +325 -3
  97. package/packages/model-runtime/src/providers/giteeai/index.ts +23 -6
  98. package/packages/model-runtime/src/providers/github/index.test.ts +532 -3
  99. package/packages/model-runtime/src/providers/github/index.ts +8 -3
  100. package/packages/model-runtime/src/providers/groq/index.test.ts +344 -31
  101. package/packages/model-runtime/src/providers/groq/index.ts +8 -3
  102. package/packages/model-runtime/src/providers/higress/index.test.ts +142 -0
  103. package/packages/model-runtime/src/providers/higress/index.ts +8 -3
  104. package/packages/model-runtime/src/providers/huggingface/index.test.ts +612 -1
  105. package/packages/model-runtime/src/providers/huggingface/index.ts +9 -4
  106. package/packages/model-runtime/src/providers/hunyuan/index.test.ts +365 -1
  107. package/packages/model-runtime/src/providers/hunyuan/index.ts +9 -3
  108. package/packages/model-runtime/src/providers/infiniai/index.test.ts +71 -0
  109. package/packages/model-runtime/src/providers/internlm/index.test.ts +369 -2
  110. package/packages/model-runtime/src/providers/internlm/index.ts +10 -5
  111. package/packages/model-runtime/src/providers/jina/index.test.ts +164 -3
  112. package/packages/model-runtime/src/providers/jina/index.ts +8 -3
  113. package/packages/model-runtime/src/providers/lmstudio/index.test.ts +182 -3
  114. package/packages/model-runtime/src/providers/lmstudio/index.ts +8 -3
  115. package/packages/model-runtime/src/providers/mistral/index.test.ts +779 -27
  116. package/packages/model-runtime/src/providers/mistral/index.ts +8 -3
  117. package/packages/model-runtime/src/providers/modelscope/index.test.ts +232 -1
  118. package/packages/model-runtime/src/providers/modelscope/index.ts +8 -3
  119. package/packages/model-runtime/src/providers/moonshot/index.test.ts +489 -2
  120. package/packages/model-runtime/src/providers/moonshot/index.ts +8 -3
  121. package/packages/model-runtime/src/providers/nebius/index.test.ts +381 -3
  122. package/packages/model-runtime/src/providers/nebius/index.ts +8 -3
  123. package/packages/model-runtime/src/providers/newapi/index.test.ts +667 -3
  124. package/packages/model-runtime/src/providers/newapi/index.ts +6 -3
  125. package/packages/model-runtime/src/providers/nvidia/index.test.ts +168 -1
  126. package/packages/model-runtime/src/providers/nvidia/index.ts +12 -7
  127. package/packages/model-runtime/src/providers/ollama/index.test.ts +797 -1
  128. package/packages/model-runtime/src/providers/ollama/index.ts +8 -0
  129. package/packages/model-runtime/src/providers/ollamacloud/index.test.ts +411 -0
  130. package/packages/model-runtime/src/providers/ollamacloud/index.ts +8 -3
  131. package/packages/model-runtime/src/providers/openai/index.test.ts +171 -2
  132. package/packages/model-runtime/src/providers/openai/index.ts +8 -3
  133. package/packages/model-runtime/src/providers/openrouter/index.test.ts +1647 -95
  134. package/packages/model-runtime/src/providers/openrouter/index.ts +12 -7
  135. package/packages/model-runtime/src/providers/qiniu/index.test.ts +294 -1
  136. package/packages/model-runtime/src/providers/qiniu/index.ts +8 -3
  137. package/packages/model-runtime/src/providers/search1api/index.test.ts +1131 -11
  138. package/packages/model-runtime/src/providers/search1api/index.ts +10 -4
  139. package/packages/model-runtime/src/providers/sensenova/index.test.ts +1069 -1
  140. package/packages/model-runtime/src/providers/sensenova/index.ts +8 -3
  141. package/packages/model-runtime/src/providers/siliconcloud/index.test.ts +196 -0
  142. package/packages/model-runtime/src/providers/siliconcloud/index.ts +8 -3
  143. package/packages/model-runtime/src/providers/spark/index.test.ts +293 -1
  144. package/packages/model-runtime/src/providers/spark/index.ts +8 -3
  145. package/packages/model-runtime/src/providers/stepfun/index.test.ts +322 -3
  146. package/packages/model-runtime/src/providers/stepfun/index.ts +8 -3
  147. package/packages/model-runtime/src/providers/tencentcloud/index.test.ts +182 -3
  148. package/packages/model-runtime/src/providers/tencentcloud/index.ts +8 -3
  149. package/packages/model-runtime/src/providers/togetherai/index.test.ts +359 -4
  150. package/packages/model-runtime/src/providers/togetherai/index.ts +12 -5
  151. package/packages/model-runtime/src/providers/v0/index.test.ts +341 -0
  152. package/packages/model-runtime/src/providers/v0/index.ts +20 -6
  153. package/packages/model-runtime/src/providers/vercelaigateway/index.test.ts +710 -0
  154. package/packages/model-runtime/src/providers/vercelaigateway/index.ts +19 -13
  155. package/packages/model-runtime/src/providers/vllm/index.test.ts +45 -1
  156. package/packages/model-runtime/src/providers/volcengine/index.test.ts +75 -0
  157. package/packages/model-runtime/src/providers/wenxin/index.test.ts +144 -1
  158. package/packages/model-runtime/src/providers/wenxin/index.ts +8 -3
  159. package/packages/model-runtime/src/providers/xai/index.test.ts +105 -1
  160. package/packages/model-runtime/src/providers/xinference/index.test.ts +70 -1
  161. package/packages/model-runtime/src/providers/zeroone/index.test.ts +327 -3
  162. package/packages/model-runtime/src/providers/zeroone/index.ts +23 -6
  163. package/packages/model-runtime/src/providers/zhipu/index.test.ts +908 -236
  164. package/packages/model-runtime/src/providers/zhipu/index.ts +8 -3
  165. package/packages/model-runtime/src/types/structureOutput.ts +5 -1
  166. package/packages/model-runtime/vitest.config.mts +7 -1
  167. package/packages/types/src/aiChat.ts +20 -2
  168. package/packages/types/src/serverConfig.ts +7 -1
  169. package/packages/types/src/tool/index.ts +1 -0
  170. package/packages/types/src/tool/tool.ts +33 -0
  171. package/packages/types/src/user/settings/image.ts +3 -0
  172. package/packages/types/src/user/settings/index.ts +3 -0
  173. package/src/app/[variants]/(main)/settings/_layout/SettingsContent.tsx +3 -0
  174. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +8 -3
  175. package/src/app/[variants]/(main)/settings/image/index.tsx +74 -0
  176. package/src/components/FormInput/FormSliderWithInput.tsx +40 -0
  177. package/src/components/FormInput/index.ts +1 -0
  178. package/src/envs/image.ts +27 -0
  179. package/src/features/Conversation/Messages/Assistant/index.tsx +1 -1
  180. package/src/features/Conversation/Messages/User/index.tsx +2 -2
  181. package/src/hooks/useFetchAiImageConfig.ts +12 -17
  182. package/src/locales/default/setting.ts +8 -0
  183. package/src/server/globalConfig/index.ts +5 -0
  184. package/src/server/routers/lambda/aiChat.ts +2 -0
  185. package/src/store/global/initialState.ts +1 -0
  186. package/src/store/image/slices/generationConfig/action.test.ts +17 -0
  187. package/src/store/image/slices/generationConfig/action.ts +18 -21
  188. package/src/store/image/slices/generationConfig/initialState.ts +3 -2
  189. package/src/store/user/slices/common/action.ts +1 -0
  190. package/src/store/user/slices/settings/selectors/settings.ts +3 -0
@@ -14,6 +14,7 @@ interface TesstProviderParams {
14
14
  provider: string;
15
15
  test?: {
16
16
  skipAPICall?: boolean;
17
+ skipErrorHandle?: boolean;
17
18
  };
18
19
  }
19
20
 
@@ -109,165 +110,167 @@ export const testProvider = ({
109
110
  });
110
111
  }
111
112
 
112
- describe('Error', () => {
113
- it('should return ProviderBizError with an openai error response when OpenAI.APIError is thrown', async () => {
114
- // Arrange
115
- const apiError = new OpenAI.APIError(
116
- 400,
117
- {
118
- error: {
119
- message: 'Bad Request',
120
- },
121
- status: 400,
122
- },
123
- 'Error message',
124
- {},
125
- );
126
-
127
- vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
128
-
129
- // Act
130
- try {
131
- await instance.chat({
132
- messages: [{ content: 'Hello', role: 'user' }],
133
- model: chatModel,
134
- temperature: 0,
135
- });
136
- } catch (e) {
137
- expect(e).toEqual({
138
- endpoint: defaultBaseURL,
139
- error: {
140
- error: { message: 'Bad Request' },
113
+ if (!test.skipErrorHandle) {
114
+ describe('Error', () => {
115
+ it('should return ProviderBizError with an openai error response when OpenAI.APIError is thrown', async () => {
116
+ // Arrange
117
+ const apiError = new OpenAI.APIError(
118
+ 400,
119
+ {
120
+ error: {
121
+ message: 'Bad Request',
122
+ },
141
123
  status: 400,
142
124
  },
143
- errorType: bizErrorType,
144
- provider,
145
- });
146
- }
147
- });
148
-
149
- it('should throw AgentRuntimeError with InvalidProviderAPIKey if no apiKey is provided', async () => {
150
- try {
151
- new Runtime({});
152
- } catch (e) {
153
- expect(e).toEqual({ errorType: invalidErrorType });
154
- }
155
- });
156
-
157
- it('should return ProviderBizError with the cause when OpenAI.APIError is thrown with cause', async () => {
158
- // Arrange
159
- const errorInfo = {
160
- cause: {
161
- message: 'api is undefined',
162
- },
163
- };
164
- const apiError = new OpenAI.APIError(400, errorInfo, 'module error', {});
125
+ 'Error message',
126
+ {},
127
+ );
128
+
129
+ vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
130
+
131
+ // Act
132
+ try {
133
+ await instance.chat({
134
+ messages: [{ content: 'Hello', role: 'user' }],
135
+ model: chatModel,
136
+ temperature: 0,
137
+ });
138
+ } catch (e) {
139
+ expect(e).toEqual({
140
+ endpoint: defaultBaseURL,
141
+ error: {
142
+ error: { message: 'Bad Request' },
143
+ status: 400,
144
+ },
145
+ errorType: bizErrorType,
146
+ provider,
147
+ });
148
+ }
149
+ });
165
150
 
166
- vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
151
+ it('should throw AgentRuntimeError with InvalidProviderAPIKey if no apiKey is provided', async () => {
152
+ try {
153
+ new Runtime({});
154
+ } catch (e) {
155
+ expect(e).toEqual({ errorType: invalidErrorType });
156
+ }
157
+ });
167
158
 
168
- // Act
169
- try {
170
- await instance.chat({
171
- messages: [{ content: 'Hello', role: 'user' }],
172
- model: chatModel,
173
- temperature: 0,
174
- });
175
- } catch (e) {
176
- expect(e).toEqual({
177
- endpoint: defaultBaseURL,
178
- error: {
179
- cause: { message: 'api is undefined' },
159
+ it('should return ProviderBizError with the cause when OpenAI.APIError is thrown with cause', async () => {
160
+ // Arrange
161
+ const errorInfo = {
162
+ cause: {
163
+ message: 'api is undefined',
180
164
  },
181
- errorType: bizErrorType,
182
- provider,
183
- });
184
- }
185
- });
186
-
187
- it('should return ProviderBizError with an cause response with desensitize Url', async () => {
188
- // Arrange
189
- const errorInfo = {
190
- cause: { message: 'api is undefined' },
191
- };
192
- const apiError = new OpenAI.APIError(400, errorInfo, 'module error', {});
193
-
194
- instance = new Runtime({
195
- apiKey: 'test',
196
-
197
- baseURL: 'https://api.abc.com/v1',
165
+ };
166
+ const apiError = new OpenAI.APIError(400, errorInfo, 'module error', {});
167
+
168
+ vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
169
+
170
+ // Act
171
+ try {
172
+ await instance.chat({
173
+ messages: [{ content: 'Hello', role: 'user' }],
174
+ model: chatModel,
175
+ temperature: 0,
176
+ });
177
+ } catch (e) {
178
+ expect(e).toEqual({
179
+ endpoint: defaultBaseURL,
180
+ error: {
181
+ cause: { message: 'api is undefined' },
182
+ },
183
+ errorType: bizErrorType,
184
+ provider,
185
+ });
186
+ }
198
187
  });
199
188
 
200
- vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
201
-
202
- // Act
203
- try {
204
- await instance.chat({
205
- messages: [{ content: 'Hello', role: 'user' }],
206
- model: chatModel,
207
- temperature: 0,
208
- });
209
- } catch (e) {
210
- expect(e).toEqual({
211
- endpoint: 'https://api.***.com/v1',
212
- error: {
213
- cause: { message: 'api is undefined' },
214
- },
215
- errorType: bizErrorType,
216
- provider,
217
- });
218
- }
219
- });
189
+ it('should return ProviderBizError with an cause response with desensitize Url', async () => {
190
+ // Arrange
191
+ const errorInfo = {
192
+ cause: { message: 'api is undefined' },
193
+ };
194
+ const apiError = new OpenAI.APIError(400, errorInfo, 'module error', {});
220
195
 
221
- it(`should throw an InvalidAPIKey error type on 401 status code`, async () => {
222
- // Mock the API call to simulate a 401 error
223
- const error = new Error('Unauthorized') as any;
224
- error.status = 401;
225
- vi.mocked(instance['client'].chat.completions.create).mockRejectedValue(error);
196
+ instance = new Runtime({
197
+ apiKey: 'test',
226
198
 
227
- try {
228
- await instance.chat({
229
- messages: [{ content: 'Hello', role: 'user' }],
230
- model: chatModel,
231
- temperature: 0,
232
- });
233
- } catch (e) {
234
- // Expect the chat method to throw an error with InvalidHunyuanAPIKey
235
- expect(e).toEqual({
236
- endpoint: defaultBaseURL,
237
- error: error,
238
- errorType: invalidErrorType,
239
- provider,
199
+ baseURL: 'https://api.abc.com/v1',
240
200
  });
241
- }
242
- });
243
201
 
244
- it('should return AgentRuntimeError for non-OpenAI errors', async () => {
245
- // Arrange
246
- const genericError = new Error('Generic Error');
202
+ vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(apiError);
203
+
204
+ // Act
205
+ try {
206
+ await instance.chat({
207
+ messages: [{ content: 'Hello', role: 'user' }],
208
+ model: chatModel,
209
+ temperature: 0,
210
+ });
211
+ } catch (e) {
212
+ expect(e).toEqual({
213
+ endpoint: 'https://api.***.com/v1',
214
+ error: {
215
+ cause: { message: 'api is undefined' },
216
+ },
217
+ errorType: bizErrorType,
218
+ provider,
219
+ });
220
+ }
221
+ });
247
222
 
248
- vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(genericError);
223
+ it(`should throw an InvalidAPIKey error type on 401 status code`, async () => {
224
+ // Mock the API call to simulate a 401 error
225
+ const error = new Error('Unauthorized') as any;
226
+ error.status = 401;
227
+ vi.mocked(instance['client'].chat.completions.create).mockRejectedValue(error);
228
+
229
+ try {
230
+ await instance.chat({
231
+ messages: [{ content: 'Hello', role: 'user' }],
232
+ model: chatModel,
233
+ temperature: 0,
234
+ });
235
+ } catch (e) {
236
+ // Expect the chat method to throw an error with InvalidHunyuanAPIKey
237
+ expect(e).toEqual({
238
+ endpoint: defaultBaseURL,
239
+ error: error,
240
+ errorType: invalidErrorType,
241
+ provider,
242
+ });
243
+ }
244
+ });
249
245
 
250
- // Act
251
- try {
252
- await instance.chat({
253
- messages: [{ content: 'Hello', role: 'user' }],
254
- model: chatModel,
255
- temperature: 0,
256
- });
257
- } catch (e) {
258
- expect(e).toEqual({
259
- endpoint: defaultBaseURL,
260
- error: {
261
- cause: genericError.cause,
262
- message: genericError.message,
263
- name: genericError.name,
264
- },
265
- errorType: 'AgentRuntimeError',
266
- provider,
267
- });
268
- }
246
+ it('should return AgentRuntimeError for non-OpenAI errors', async () => {
247
+ // Arrange
248
+ const genericError = new Error('Generic Error');
249
+
250
+ vi.spyOn(instance['client'].chat.completions, 'create').mockRejectedValue(genericError);
251
+
252
+ // Act
253
+ try {
254
+ await instance.chat({
255
+ messages: [{ content: 'Hello', role: 'user' }],
256
+ model: chatModel,
257
+ temperature: 0,
258
+ });
259
+ } catch (e) {
260
+ expect(e).toEqual({
261
+ endpoint: defaultBaseURL,
262
+ error: {
263
+ cause: genericError.cause,
264
+ message: genericError.message,
265
+ name: genericError.name,
266
+ },
267
+ errorType: 'AgentRuntimeError',
268
+ provider,
269
+ });
270
+ }
271
+ });
269
272
  });
270
- });
273
+ }
271
274
 
272
275
  describe('DEBUG', () => {
273
276
  it(`should call debugStream and return StreamingTextResponse when ${chatDebugEnv} is 1`, async () => {
@@ -0,0 +1,60 @@
1
+ // @vitest-environment node
2
+ import { ModelProvider } from 'model-bank';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+
5
+ import { testProvider } from '../../providerTestUtils';
6
+ import { AgentRuntimeErrorType } from '../../types/error';
7
+ import { Lobe302AI, params } from './index';
8
+
9
+ testProvider({
10
+ Runtime: Lobe302AI,
11
+ provider: ModelProvider.Ai302,
12
+ defaultBaseURL: 'https://api.302.ai/v1',
13
+ chatDebugEnv: 'DEBUG_AI302_CHAT_COMPLETION',
14
+ chatModel: 'gpt-3.5-turbo',
15
+ invalidErrorType: 'InvalidProviderAPIKey',
16
+ bizErrorType: 'ProviderBizError',
17
+ test: {
18
+ skipAPICall: true,
19
+ skipErrorHandle: true,
20
+ },
21
+ });
22
+
23
+ describe('Lobe302AI - params', () => {
24
+ it('should have correct baseURL', () => {
25
+ expect(params.baseURL).toBe('https://api.302.ai/v1');
26
+ expect(params.provider).toBe(ModelProvider.Ai302);
27
+ });
28
+
29
+ describe('handleError', () => {
30
+ it('should handle 401 error as InvalidProviderAPIKey', () => {
31
+ const error = new Response('Unauthorized', { status: 401 });
32
+ const result = params.chatCompletion?.handleError?.(error);
33
+
34
+ expect(result?.errorType).toBe(AgentRuntimeErrorType.InvalidProviderAPIKey);
35
+ expect(result?.error).toBe(401);
36
+ });
37
+
38
+ it('should handle error with status property', () => {
39
+ const error = { status: 401, message: 'Unauthorized' };
40
+ const result = params.chatCompletion?.handleError?.(error);
41
+
42
+ expect(result?.errorType).toBe(AgentRuntimeErrorType.InvalidProviderAPIKey);
43
+ });
44
+
45
+ it('should return error for non-401 status', () => {
46
+ const error = new Response('Bad Request', { status: 400 });
47
+ const result = params.chatCompletion?.handleError?.(error);
48
+
49
+ expect(result?.error).toBe(error);
50
+ expect(result?.errorType).toBeUndefined();
51
+ });
52
+
53
+ it('should return error for generic errors', () => {
54
+ const error = new Error('Network error');
55
+ const result = params.chatCompletion?.handleError?.(error);
56
+
57
+ expect(result?.error).toBe(error);
58
+ });
59
+ });
60
+ });
@@ -1,6 +1,9 @@
1
1
  import { ModelProvider } from 'model-bank';
2
2
 
3
- import { createOpenAICompatibleRuntime } from '../../core/openaiCompatibleFactory';
3
+ import {
4
+ OpenAICompatibleFactoryOptions,
5
+ createOpenAICompatibleRuntime,
6
+ } from '../../core/openaiCompatibleFactory';
4
7
  import { ChatCompletionErrorPayload } from '../../types';
5
8
  import { AgentRuntimeErrorType } from '../../types/error';
6
9
  import { processMultiProviderModelList } from '../../utils/modelParse';
@@ -9,7 +12,7 @@ export interface Ai302ModelCard {
9
12
  id: string;
10
13
  }
11
14
 
12
- export const Lobe302AI = createOpenAICompatibleRuntime({
15
+ export const params = {
13
16
  baseURL: 'https://api.302.ai/v1',
14
17
  chatCompletion: {
15
18
  handleError: (error: any): Omit<ChatCompletionErrorPayload, 'provider'> | undefined => {
@@ -32,7 +35,7 @@ export const Lobe302AI = createOpenAICompatibleRuntime({
32
35
  },
33
36
  },
34
37
  debug: {
35
- chatCompletion: () => process.env.DEBUG_SILICONCLOUD_CHAT_COMPLETION === '1',
38
+ chatCompletion: () => process.env.DEBUG_AI302_CHAT_COMPLETION === '1',
36
39
  },
37
40
  errorType: {
38
41
  bizError: AgentRuntimeErrorType.ProviderBizError,
@@ -45,4 +48,6 @@ export const Lobe302AI = createOpenAICompatibleRuntime({
45
48
  return processMultiProviderModelList(modelList, 'ai302');
46
49
  },
47
50
  provider: ModelProvider.Ai302,
48
- });
51
+ } satisfies OpenAICompatibleFactoryOptions;
52
+
53
+ export const Lobe302AI = createOpenAICompatibleRuntime(params);