Przeglądaj źródła

fix(cerebras): ensure all tools have consistent strict mode values (#10589)

Co-authored-by: Roo Code <[email protected]>
roomote[bot] 3 tygodni temu
rodzic
commit
d97e540ac6

+ 73 - 0
src/api/providers/__tests__/cerebras.spec.ts

@@ -173,4 +173,77 @@ describe("CerebrasHandler", () => {
 			// Test fallback token estimation logic
 			// Test fallback token estimation logic
 		})
 		})
 	})
 	})
+
+	describe("convertToolsForOpenAI", () => {
+		it("should set all tools to strict: false for Cerebras API consistency", () => {
+			// Access the protected method through a test subclass
+			const regularTool = {
+				type: "function",
+				function: {
+					name: "read_file",
+					parameters: {
+						type: "object",
+						properties: {
+							path: { type: "string" },
+						},
+						required: ["path"],
+					},
+				},
+			}
+
+			// MCP tool with the 'mcp--' prefix
+			const mcpTool = {
+				type: "function",
+				function: {
+					name: "mcp--server--tool",
+					parameters: {
+						type: "object",
+						properties: {
+							arg: { type: "string" },
+						},
+					},
+				},
+			}
+
+			// Create a test wrapper to access protected method
+			class TestCerebrasHandler extends CerebrasHandler {
+				public testConvertToolsForOpenAI(tools: any[]) {
+					return this.convertToolsForOpenAI(tools)
+				}
+			}
+
+			const testHandler = new TestCerebrasHandler({ cerebrasApiKey: "test" })
+			const converted = testHandler.testConvertToolsForOpenAI([regularTool, mcpTool])
+
+			// Both tools should have strict: false
+			expect(converted).toHaveLength(2)
+			expect(converted![0].function.strict).toBe(false)
+			expect(converted![1].function.strict).toBe(false)
+		})
+
+		it("should return undefined when tools is undefined", () => {
+			class TestCerebrasHandler extends CerebrasHandler {
+				public testConvertToolsForOpenAI(tools: any[] | undefined) {
+					return this.convertToolsForOpenAI(tools)
+				}
+			}
+
+			const testHandler = new TestCerebrasHandler({ cerebrasApiKey: "test" })
+			expect(testHandler.testConvertToolsForOpenAI(undefined)).toBeUndefined()
+		})
+
+		it("should pass through non-function tools unchanged", () => {
+			class TestCerebrasHandler extends CerebrasHandler {
+				public testConvertToolsForOpenAI(tools: any[]) {
+					return this.convertToolsForOpenAI(tools)
+				}
+			}
+
+			const nonFunctionTool = { type: "other", data: "test" }
+			const testHandler = new TestCerebrasHandler({ cerebrasApiKey: "test" })
+			const converted = testHandler.testConvertToolsForOpenAI([nonFunctionTool])
+
+			expect(converted![0]).toEqual(nonFunctionTool)
+		})
+	})
 })
 })

+ 27 - 0
src/api/providers/cerebras.ts

@@ -91,6 +91,33 @@ export class CerebrasHandler extends BaseProvider implements SingleCompletionHan
 		return result
 		return result
 	}
 	}
 
 
+	/**
+	 * Override convertToolsForOpenAI to ensure all tools have consistent strict values.
+	 * Cerebras API requires all tools to have the same strict mode setting.
+	 * We use strict: false for all tools since MCP tools cannot use strict mode
+	 * (they have optional parameters from the MCP server schema).
+	 */
+	protected override convertToolsForOpenAI(tools: any[] | undefined): any[] | undefined {
+		if (!tools) {
+			return undefined
+		}
+
+		return tools.map((tool) => {
+			if (tool.type !== "function") {
+				return tool
+			}
+
+			return {
+				...tool,
+				function: {
+					...tool.function,
+					strict: false,
+					parameters: this.convertToolSchemaForOpenAI(tool.function.parameters),
+				},
+			}
+		})
+	}
+
 	async *createMessage(
 	async *createMessage(
 		systemPrompt: string,
 		systemPrompt: string,
 		messages: Anthropic.Messages.MessageParam[],
 		messages: Anthropic.Messages.MessageParam[],