Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit 332b66c

Browse files
committed
fix(lm-studio): only include parallel_tool_calls when explicitly enabled
This fixes an issue where GLM4.5 and other models via LM Studio get stuck in a loop repeatedly reading the same file. The problem was introduced in commit ed35b09 which changed parallel_tool_calls default from false to true. By only including the parallel_tool_calls parameter when explicitly set to true, we maintain compatibility with models that do not support this parameter (e.g., GLM4.5). This follows the same pattern used in commit 2d4dba0 for LiteLLM/Bedrock compatibility. Fixes #11071
1 parent 40b2bdc commit 332b66c

2 files changed

Lines changed: 13 additions & 8 deletions

File tree

src/api/providers/__tests__/lmstudio-native-tools.spec.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ describe("LmStudioHandler Native Tools", () => {
8282
]),
8383
}),
8484
)
85-
// parallel_tool_calls should be true by default when not explicitly set
85+
// parallel_tool_calls should NOT be included by default for compatibility with
86+
// models that don't support it (e.g., GLM4.5)
8687
const callArgs = mockCreate.mock.calls[0][0]
87-
expect(callArgs).toHaveProperty("parallel_tool_calls", true)
88+
expect(callArgs).not.toHaveProperty("parallel_tool_calls")
8889
})
8990

9091
it("should include tool_choice when provided", async () => {
@@ -128,8 +129,9 @@ describe("LmStudioHandler Native Tools", () => {
128129
// Tools are now always present (minimum 6 from ALWAYS_AVAILABLE_TOOLS)
129130
expect(callArgs).toHaveProperty("tools")
130131
expect(callArgs).toHaveProperty("tool_choice")
131-
// parallel_tool_calls should be true by default when not explicitly set
132-
expect(callArgs).toHaveProperty("parallel_tool_calls", true)
132+
// parallel_tool_calls should NOT be included by default for compatibility with
133+
// models that don't support it (e.g., GLM4.5)
134+
expect(callArgs).not.toHaveProperty("parallel_tool_calls")
133135
})
134136

135137
it("should yield tool_call_partial chunks during streaming", async () => {
@@ -283,7 +285,7 @@ describe("LmStudioHandler Native Tools", () => {
283285
expect(endChunks[0].id).toBe("call_lmstudio_test")
284286
})
285287

286-
it("should work with parallel tool calls disabled (sends false)", async () => {
288+
it("should work with parallel tool calls disabled (omits parameter)", async () => {
287289
mockCreate.mockImplementationOnce(() => ({
288290
[Symbol.asyncIterator]: async function* () {
289291
yield {
@@ -299,9 +301,10 @@ describe("LmStudioHandler Native Tools", () => {
299301
})
300302
await stream.next()
301303

302-
// When parallelToolCalls is false, the parameter should be sent as false
304+
// When parallelToolCalls is false, the parameter should NOT be included
305+
// to maintain compatibility with models that don't support it
303306
const callArgs = mockCreate.mock.calls[0][0]
304-
expect(callArgs).toHaveProperty("parallel_tool_calls", false)
307+
expect(callArgs).not.toHaveProperty("parallel_tool_calls")
305308
})
306309

307310
it("should handle reasoning content alongside tool calls", async () => {

src/api/providers/lm-studio.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@ export class LmStudioHandler extends BaseProvider implements SingleCompletionHan
9090
stream: true,
9191
tools: this.convertToolsForOpenAI(metadata?.tools),
9292
tool_choice: metadata?.tool_choice,
93-
parallel_tool_calls: metadata?.parallelToolCalls ?? true,
93+
// Only include parallel_tool_calls when explicitly enabled to maintain
94+
// compatibility with models that don't support it (e.g., GLM4.5)
95+
...(metadata?.parallelToolCalls === true && { parallel_tool_calls: true }),
9496
}
9597

9698
if (this.options.lmStudioSpeculativeDecodingEnabled && this.options.lmStudioDraftModelId) {

0 commit comments

Comments
 (0)