@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
@@ -1,11 +1,335 @@
1
1
  // @vitest-environment node
2
+ import { ModelProvider } from 'model-bank';
3
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
4
+
2
5
  import { testProvider } from '../../providerTestUtils';
3
- import { LobeZeroOneAI } from './index';
6
+ import { LobeZeroOneAI, params } from './index';
4
7
 
5
8
  testProvider({
6
9
  Runtime: LobeZeroOneAI,
7
- provider: 'zeroone',
8
- defaultBaseURL: 'https://api.lingyiwanwu.com/v1',
9
10
  chatDebugEnv: 'DEBUG_ZEROONE_CHAT_COMPLETION',
10
11
  chatModel: 'yi-34b-chat-0205',
12
+ defaultBaseURL: 'https://api.lingyiwanwu.com/v1',
13
+ provider: ModelProvider.ZeroOne,
14
+ });
15
+
16
+ describe('LobeZeroOneAI - custom features', () => {
17
+ let instance: InstanceType<typeof LobeZeroOneAI>;
18
+
19
+ beforeEach(() => {
20
+ instance = new LobeZeroOneAI({ apiKey: 'test_api_key' });
21
+ vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(
22
+ new ReadableStream() as any,
23
+ );
24
+ });
25
+
26
+ describe('params configuration', () => {
27
+ it('should export params object with correct baseURL', () => {
28
+ expect(params.baseURL).toBe('https://api.lingyiwanwu.com/v1');
29
+ });
30
+
31
+ it('should export params with correct provider', () => {
32
+ expect(params.provider).toBe(ModelProvider.ZeroOne);
33
+ });
34
+
35
+ it('should have debug configuration', () => {
36
+ expect(params.debug).toBeDefined();
37
+ expect(params.debug.chatCompletion).toBeDefined();
38
+ expect(typeof params.debug.chatCompletion).toBe('function');
39
+ });
40
+
41
+ it('should have models function', () => {
42
+ expect(params.models).toBeDefined();
43
+ expect(typeof params.models).toBe('function');
44
+ });
45
+ });
46
+
47
+ describe('debug configuration', () => {
48
+ it('should disable debug by default', () => {
49
+ delete process.env.DEBUG_ZEROONE_CHAT_COMPLETION;
50
+ const result = params.debug.chatCompletion();
51
+ expect(result).toBe(false);
52
+ });
53
+
54
+ it('should enable debug when env is set to 1', () => {
55
+ process.env.DEBUG_ZEROONE_CHAT_COMPLETION = '1';
56
+ const result = params.debug.chatCompletion();
57
+ expect(result).toBe(true);
58
+ });
59
+
60
+ it('should disable debug when env is set to 0', () => {
61
+ process.env.DEBUG_ZEROONE_CHAT_COMPLETION = '0';
62
+ const result = params.debug.chatCompletion();
63
+ expect(result).toBe(false);
64
+ });
65
+
66
+ it('should disable debug when env is empty string', () => {
67
+ process.env.DEBUG_ZEROONE_CHAT_COMPLETION = '';
68
+ const result = params.debug.chatCompletion();
69
+ expect(result).toBe(false);
70
+ });
71
+ });
72
+
73
+ describe('models function', () => {
74
+ it('should fetch and process models with data property', async () => {
75
+ const mockClient = {
76
+ apiKey: 'test_api_key',
77
+ baseURL: 'https://api.lingyiwanwu.com/v1',
78
+ models: {
79
+ list: vi.fn().mockResolvedValue({
80
+ data: [
81
+ { id: 'yi-34b-chat-0205', object: 'model' },
82
+ { id: 'yi-lightning', object: 'model' },
83
+ ],
84
+ }),
85
+ },
86
+ } as any;
87
+
88
+ const models = await params.models!({ client: mockClient });
89
+
90
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
91
+ expect(models).toBeDefined();
92
+ expect(Array.isArray(models)).toBe(true);
93
+ });
94
+
95
+ it('should handle models list without data property (direct array)', async () => {
96
+ const mockClient = {
97
+ apiKey: 'test_api_key',
98
+ baseURL: 'https://api.lingyiwanwu.com/v1',
99
+ models: {
100
+ list: vi.fn().mockResolvedValue([
101
+ { id: 'yi-34b-chat-0205', object: 'model' },
102
+ { id: 'yi-lightning', object: 'model' },
103
+ ]),
104
+ },
105
+ } as any;
106
+
107
+ const models = await params.models!({ client: mockClient });
108
+
109
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
110
+ expect(models).toBeDefined();
111
+ expect(Array.isArray(models)).toBe(true);
112
+ });
113
+
114
+ it('should handle empty models list with data property', async () => {
115
+ const mockClient = {
116
+ apiKey: 'test_api_key',
117
+ baseURL: 'https://api.lingyiwanwu.com/v1',
118
+ models: {
119
+ list: vi.fn().mockResolvedValue({
120
+ data: [],
121
+ }),
122
+ },
123
+ } as any;
124
+
125
+ const models = await params.models!({ client: mockClient });
126
+
127
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
128
+ expect(models).toBeDefined();
129
+ expect(Array.isArray(models)).toBe(true);
130
+ expect(models).toHaveLength(0);
131
+ });
132
+
133
+ it('should handle empty models list without data property', async () => {
134
+ const mockClient = {
135
+ apiKey: 'test_api_key',
136
+ baseURL: 'https://api.lingyiwanwu.com/v1',
137
+ models: {
138
+ list: vi.fn().mockResolvedValue([]),
139
+ },
140
+ } as any;
141
+
142
+ const models = await params.models!({ client: mockClient });
143
+
144
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
145
+ expect(models).toBeDefined();
146
+ expect(Array.isArray(models)).toBe(true);
147
+ expect(models).toHaveLength(0);
148
+ });
149
+
150
+ it('should handle null response', async () => {
151
+ const mockClient = {
152
+ apiKey: 'test_api_key',
153
+ baseURL: 'https://api.lingyiwanwu.com/v1',
154
+ models: {
155
+ list: vi.fn().mockResolvedValue(null),
156
+ },
157
+ } as any;
158
+
159
+ const models = await params.models!({ client: mockClient });
160
+
161
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
162
+ expect(models).toBeDefined();
163
+ expect(Array.isArray(models)).toBe(true);
164
+ expect(models).toHaveLength(0);
165
+ });
166
+
167
+ it('should handle undefined response', async () => {
168
+ const mockClient = {
169
+ apiKey: 'test_api_key',
170
+ baseURL: 'https://api.lingyiwanwu.com/v1',
171
+ models: {
172
+ list: vi.fn().mockResolvedValue(undefined),
173
+ },
174
+ } as any;
175
+
176
+ const models = await params.models!({ client: mockClient });
177
+
178
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
179
+ expect(models).toBeDefined();
180
+ expect(Array.isArray(models)).toBe(true);
181
+ expect(models).toHaveLength(0);
182
+ });
183
+
184
+ it('should handle response with non-array data', async () => {
185
+ const mockClient = {
186
+ apiKey: 'test_api_key',
187
+ baseURL: 'https://api.lingyiwanwu.com/v1',
188
+ models: {
189
+ list: vi.fn().mockResolvedValue({
190
+ data: 'not-an-array',
191
+ }),
192
+ },
193
+ } as any;
194
+
195
+ const models = await params.models!({ client: mockClient });
196
+
197
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
198
+ expect(models).toBeDefined();
199
+ expect(Array.isArray(models)).toBe(true);
200
+ expect(models).toHaveLength(0);
201
+ });
202
+
203
+ it('should handle network error and return empty array', async () => {
204
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
205
+ const mockClient = {
206
+ apiKey: 'test_api_key',
207
+ baseURL: 'https://api.lingyiwanwu.com/v1',
208
+ models: {
209
+ list: vi.fn().mockRejectedValue(new Error('Network error')),
210
+ },
211
+ } as any;
212
+
213
+ const models = await params.models!({ client: mockClient });
214
+
215
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
216
+ expect(models).toBeDefined();
217
+ expect(Array.isArray(models)).toBe(true);
218
+ expect(models).toHaveLength(0);
219
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
220
+ 'Failed to fetch ZeroOne models. Please ensure your ZeroOne API key is valid:',
221
+ expect.any(Error),
222
+ );
223
+
224
+ consoleWarnSpy.mockRestore();
225
+ });
226
+
227
+ it('should handle API authentication error and return empty array', async () => {
228
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
229
+ const mockClient = {
230
+ apiKey: 'invalid_key',
231
+ baseURL: 'https://api.lingyiwanwu.com/v1',
232
+ models: {
233
+ list: vi.fn().mockRejectedValue(new Error('401 Unauthorized')),
234
+ },
235
+ } as any;
236
+
237
+ const models = await params.models!({ client: mockClient });
238
+
239
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
240
+ expect(models).toEqual([]);
241
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
242
+ 'Failed to fetch ZeroOne models. Please ensure your ZeroOne API key is valid:',
243
+ expect.any(Error),
244
+ );
245
+
246
+ consoleWarnSpy.mockRestore();
247
+ });
248
+
249
+ it('should handle API rate limit error and return empty array', async () => {
250
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
251
+ const mockClient = {
252
+ apiKey: 'test_api_key',
253
+ baseURL: 'https://api.lingyiwanwu.com/v1',
254
+ models: {
255
+ list: vi.fn().mockRejectedValue(new Error('429 Too Many Requests')),
256
+ },
257
+ } as any;
258
+
259
+ const models = await params.models!({ client: mockClient });
260
+
261
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
262
+ expect(models).toEqual([]);
263
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
264
+ 'Failed to fetch ZeroOne models. Please ensure your ZeroOne API key is valid:',
265
+ expect.any(Error),
266
+ );
267
+
268
+ consoleWarnSpy.mockRestore();
269
+ });
270
+
271
+ it('should handle timeout error and return empty array', async () => {
272
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
273
+ const mockClient = {
274
+ apiKey: 'test_api_key',
275
+ baseURL: 'https://api.lingyiwanwu.com/v1',
276
+ models: {
277
+ list: vi.fn().mockRejectedValue(new Error('Request timeout')),
278
+ },
279
+ } as any;
280
+
281
+ const models = await params.models!({ client: mockClient });
282
+
283
+ expect(mockClient.models.list).toHaveBeenCalledTimes(1);
284
+ expect(models).toEqual([]);
285
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
286
+ 'Failed to fetch ZeroOne models. Please ensure your ZeroOne API key is valid:',
287
+ expect.any(Error),
288
+ );
289
+
290
+ consoleWarnSpy.mockRestore();
291
+ });
292
+
293
+ it('should handle malformed JSON response', async () => {
294
+ const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
295
+ const mockClient = {
296
+ apiKey: 'test_api_key',
297
+ baseURL: 'https://api.lingyiwanwu.com/v1',
298
+ models: {
299
+ list: vi.fn().mockRejectedValue(new Error('Invalid JSON')),
300
+ },
301
+ } as any;
302
+
303
+ const models = await params.models!({ client: mockClient });
304
+
305
+ expect(models).toEqual([]);
306
+ expect(consoleWarnSpy).toHaveBeenCalledWith(
307
+ 'Failed to fetch ZeroOne models. Please ensure your ZeroOne API key is valid:',
308
+ expect.any(Error),
309
+ );
310
+
311
+ consoleWarnSpy.mockRestore();
312
+ });
313
+
314
+ it('should pass correct client to processModelList', async () => {
315
+ const mockModelList = [
316
+ { id: 'yi-34b-chat-0205', object: 'model' },
317
+ { id: 'yi-lightning', object: 'model' },
318
+ ];
319
+
320
+ const mockClient = {
321
+ apiKey: 'test_api_key',
322
+ baseURL: 'https://api.lingyiwanwu.com/v1',
323
+ models: {
324
+ list: vi.fn().mockResolvedValue({ data: mockModelList }),
325
+ },
326
+ } as any;
327
+
328
+ const models = await params.models!({ client: mockClient });
329
+
330
+ // Verify processModelList was called with correct parameters
331
+ expect(models).toBeDefined();
332
+ expect(Array.isArray(models)).toBe(true);
333
+ });
334
+ });
11
335
  });
@@ -1,22 +1,39 @@
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 { MODEL_LIST_CONFIGS, processModelList } from '../../utils/modelParse';
5
8
 
6
9
  export interface ZeroOneModelCard {
7
10
  id: string;
8
11
  }
9
12
 
10
- export const LobeZeroOneAI = createOpenAICompatibleRuntime({
13
+ export const params = {
11
14
  baseURL: 'https://api.lingyiwanwu.com/v1',
12
15
  debug: {
13
16
  chatCompletion: () => process.env.DEBUG_ZEROONE_CHAT_COMPLETION === '1',
14
17
  },
15
18
  models: async ({ client }) => {
16
- const modelsPage = (await client.models.list()) as any;
17
- const modelList: ZeroOneModelCard[] = modelsPage.data;
19
+ try {
20
+ const modelsPage = (await client.models.list()) as any;
21
+ const modelList: ZeroOneModelCard[] = Array.isArray(modelsPage?.data)
22
+ ? modelsPage.data
23
+ : Array.isArray(modelsPage)
24
+ ? modelsPage
25
+ : [];
18
26
 
19
- return processModelList(modelList, MODEL_LIST_CONFIGS.zeroone);
27
+ return processModelList(modelList, MODEL_LIST_CONFIGS.zeroone);
28
+ } catch (error) {
29
+ console.warn(
30
+ 'Failed to fetch ZeroOne models. Please ensure your ZeroOne API key is valid:',
31
+ error,
32
+ );
33
+ return [];
34
+ }
20
35
  },
21
36
  provider: ModelProvider.ZeroOne,
22
- });
37
+ } satisfies OpenAICompatibleFactoryOptions;
38
+
39
+ export const LobeZeroOneAI = createOpenAICompatibleRuntime(params);