@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
@@ -1857,6 +1857,185 @@ describe('LobeOpenAICompatibleFactory', () => {
1857
1857
  });
1858
1858
  });
1859
1859
 
1860
+ describe('tools parameter support', () => {
1861
+ it('should handle tools parameter with multiple tools', async () => {
1862
+ const mockResponse = {
1863
+ choices: [
1864
+ {
1865
+ message: {
1866
+ tool_calls: [
1867
+ {
1868
+ type: 'function' as const,
1869
+ function: {
1870
+ name: 'get_weather',
1871
+ arguments: '{"city":"Tokyo","unit":"celsius"}',
1872
+ },
1873
+ },
1874
+ {
1875
+ type: 'function' as const,
1876
+ function: {
1877
+ name: 'get_time',
1878
+ arguments: '{"timezone":"Asia/Tokyo"}',
1879
+ },
1880
+ },
1881
+ ],
1882
+ },
1883
+ },
1884
+ ],
1885
+ };
1886
+
1887
+ vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(
1888
+ mockResponse as any,
1889
+ );
1890
+
1891
+ const payload = {
1892
+ messages: [{ content: 'What is the weather and time in Tokyo?', role: 'user' as const }],
1893
+ tools: [
1894
+ {
1895
+ name: 'get_weather',
1896
+ description: 'Get weather information',
1897
+ parameters: {
1898
+ type: 'object' as const,
1899
+ properties: {
1900
+ city: { type: 'string' },
1901
+ unit: { type: 'string' },
1902
+ },
1903
+ required: ['city'],
1904
+ },
1905
+ },
1906
+ {
1907
+ name: 'get_time',
1908
+ description: 'Get current time',
1909
+ parameters: {
1910
+ type: 'object' as const,
1911
+ properties: {
1912
+ timezone: { type: 'string' },
1913
+ },
1914
+ required: ['timezone'],
1915
+ },
1916
+ },
1917
+ ],
1918
+ model: 'gpt-4o',
1919
+ };
1920
+
1921
+ const result = await instance.generateObject(payload);
1922
+
1923
+ expect(instance['client'].chat.completions.create).toHaveBeenCalledWith(
1924
+ {
1925
+ messages: payload.messages,
1926
+ model: payload.model,
1927
+ tool_choice: 'required',
1928
+ tools: [
1929
+ {
1930
+ type: 'function',
1931
+ function: {
1932
+ name: 'get_weather',
1933
+ description: 'Get weather information',
1934
+ parameters: {
1935
+ type: 'object',
1936
+ properties: {
1937
+ city: { type: 'string' },
1938
+ unit: { type: 'string' },
1939
+ },
1940
+ required: ['city'],
1941
+ },
1942
+ },
1943
+ },
1944
+ {
1945
+ type: 'function',
1946
+ function: {
1947
+ name: 'get_time',
1948
+ description: 'Get current time',
1949
+ parameters: {
1950
+ type: 'object',
1951
+ properties: {
1952
+ timezone: { type: 'string' },
1953
+ },
1954
+ required: ['timezone'],
1955
+ },
1956
+ },
1957
+ },
1958
+ ],
1959
+ user: undefined,
1960
+ },
1961
+ { headers: undefined, signal: undefined },
1962
+ );
1963
+
1964
+ expect(result).toEqual([
1965
+ { arguments: { city: 'Tokyo', unit: 'celsius' }, name: 'get_weather' },
1966
+ { arguments: { timezone: 'Asia/Tokyo' }, name: 'get_time' },
1967
+ ]);
1968
+ });
1969
+
1970
+ it('should handle tools parameter with systemRole', async () => {
1971
+ const mockResponse = {
1972
+ choices: [
1973
+ {
1974
+ message: {
1975
+ tool_calls: [
1976
+ {
1977
+ type: 'function' as const,
1978
+ function: {
1979
+ name: 'calculate',
1980
+ arguments: '{"result":8}',
1981
+ },
1982
+ },
1983
+ ],
1984
+ },
1985
+ },
1986
+ ],
1987
+ };
1988
+
1989
+ vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(
1990
+ mockResponse as any,
1991
+ );
1992
+
1993
+ const payload = {
1994
+ messages: [{ content: 'Add 5 and 3', role: 'user' as const }],
1995
+ tools: [
1996
+ {
1997
+ name: 'calculate',
1998
+ description: 'Perform calculation',
1999
+ parameters: {
2000
+ type: 'object' as const,
2001
+ properties: {
2002
+ result: { type: 'number' },
2003
+ },
2004
+ required: ['result'],
2005
+ },
2006
+ },
2007
+ ],
2008
+ systemRole: 'You are a helpful calculator',
2009
+ model: 'gpt-4o',
2010
+ };
2011
+
2012
+ const result = await instance.generateObject(payload);
2013
+
2014
+ expect(instance['client'].chat.completions.create).toHaveBeenCalledWith(
2015
+ expect.objectContaining({
2016
+ messages: [
2017
+ { content: 'Add 5 and 3', role: 'user' },
2018
+ { content: 'You are a helpful calculator', role: 'system' },
2019
+ ],
2020
+ }),
2021
+ expect.any(Object),
2022
+ );
2023
+
2024
+ expect(result).toEqual([{ arguments: { result: 8 }, name: 'calculate' }]);
2025
+ });
2026
+
2027
+ it('should throw error when neither tools nor schema is provided', async () => {
2028
+ const payload = {
2029
+ messages: [{ content: 'Generate data', role: 'user' as const }],
2030
+ model: 'gpt-4o',
2031
+ };
2032
+
2033
+ await expect(instance.generateObject(payload as any)).rejects.toThrow(
2034
+ 'tools or schema is required',
2035
+ );
2036
+ });
2037
+ });
2038
+
1860
2039
  describe('tool calling fallback', () => {
1861
2040
  let instanceWithToolCalling: any;
1862
2041
 
@@ -1930,7 +2109,9 @@ describe('LobeOpenAICompatibleFactory', () => {
1930
2109
  { headers: undefined, signal: undefined },
1931
2110
  );
1932
2111
 
1933
- expect(result).toEqual({ name: 'Alice', age: 28 });
2112
+ expect(result).toEqual([
2113
+ { arguments: { name: 'Alice', age: 28 }, name: 'person_extractor' },
2114
+ ]);
1934
2115
  });
1935
2116
 
1936
2117
  it('should return undefined when no tool call found', async () => {
@@ -1960,7 +2141,7 @@ describe('LobeOpenAICompatibleFactory', () => {
1960
2141
 
1961
2142
  const result = await instanceWithToolCalling.generateObject(payload);
1962
2143
 
1963
- expect(consoleSpy).toHaveBeenCalledWith('No tool call found in response');
2144
+ expect(consoleSpy).toHaveBeenCalledWith('parse tool call arguments error:', undefined);
1964
2145
  expect(result).toBeUndefined();
1965
2146
 
1966
2147
  consoleSpy.mockRestore();
@@ -2001,7 +2182,10 @@ describe('LobeOpenAICompatibleFactory', () => {
2001
2182
 
2002
2183
  const result = await instanceWithToolCalling.generateObject(payload);
2003
2184
 
2004
- expect(consoleSpy).toHaveBeenCalledWith('parse tool call arguments error:', 'invalid json');
2185
+ expect(consoleSpy).toHaveBeenCalledWith(
2186
+ 'parse tool call arguments error:',
2187
+ mockResponse.choices[0].message.tool_calls,
2188
+ );
2005
2189
  expect(result).toBeUndefined();
2006
2190
 
2007
2191
  consoleSpy.mockRestore();
@@ -2052,7 +2236,7 @@ describe('LobeOpenAICompatibleFactory', () => {
2052
2236
  { headers: options.headers, signal: options.signal },
2053
2237
  );
2054
2238
 
2055
- expect(result).toEqual({ data: 'test' });
2239
+ expect(result).toEqual([{ arguments: { data: 'test' }, name: 'data_extractor' }]);
2056
2240
  });
2057
2241
  });
2058
2242
  });
@@ -67,7 +67,7 @@ export interface CustomClientOptions<T extends Record<string, any> = any> {
67
67
  createClient?: (options: ConstructorOptions<T>) => any;
68
68
  }
69
69
 
70
- interface OpenAICompatibleFactoryOptions<T extends Record<string, any> = any> {
70
+ export interface OpenAICompatibleFactoryOptions<T extends Record<string, any> = any> {
71
71
  apiKey?: string;
72
72
  baseURL?: string;
73
73
  chatCompletion?: {
@@ -396,7 +396,40 @@ export const createOpenAICompatibleRuntime = <T extends Record<string, any> = an
396
396
  }
397
397
 
398
398
  async generateObject(payload: GenerateObjectPayload, options?: GenerateObjectOptions) {
399
- const { messages, schema, model, responseApi } = payload;
399
+ const { messages, schema, model, responseApi, tools, systemRole } = payload;
400
+
401
+ if (tools) {
402
+ const msgs = messages;
403
+
404
+ if (!!systemRole) {
405
+ msgs.push({ content: systemRole, role: 'system' });
406
+ }
407
+
408
+ const res = await this.client.chat.completions.create(
409
+ {
410
+ messages: msgs,
411
+ model,
412
+ tool_choice: 'required',
413
+ tools: tools.map((tool) => ({ function: tool, type: 'function' })),
414
+ user: options?.user,
415
+ },
416
+ { headers: options?.headers, signal: options?.signal },
417
+ );
418
+
419
+ const toolCalls = res.choices[0].message.tool_calls!;
420
+
421
+ try {
422
+ return toolCalls.map((item) => ({
423
+ arguments: JSON.parse(item.function.arguments),
424
+ name: item.function.name,
425
+ }));
426
+ } catch {
427
+ console.error('parse tool call arguments error:', res);
428
+ return undefined;
429
+ }
430
+ }
431
+
432
+ if (!schema) throw new Error('tools or schema is required');
400
433
 
401
434
  // Use tool calling fallback if configured
402
435
  if (generateObjectConfig?.useToolsCalling) {
@@ -421,17 +454,15 @@ export const createOpenAICompatibleRuntime = <T extends Record<string, any> = an
421
454
  { headers: options?.headers, signal: options?.signal },
422
455
  );
423
456
 
424
- const toolCall = res.choices[0].message.tool_calls?.[0];
425
-
426
- if (!toolCall || toolCall.type !== 'function') {
427
- console.error('No tool call found in response');
428
- return undefined;
429
- }
457
+ const toolCalls = res.choices[0].message.tool_calls!;
430
458
 
431
459
  try {
432
- return JSON.parse(toolCall.function.arguments);
460
+ return toolCalls.map((item) => ({
461
+ arguments: JSON.parse(item.function.arguments),
462
+ name: item.function.name,
463
+ }));
433
464
  } catch {
434
- console.error('parse tool call arguments error:', toolCall.function.arguments);
465
+ console.error('parse tool call arguments error:', toolCalls);
435
466
  return undefined;
436
467
  }
437
468
  }