fix(types): preserve sanitized tool array contracts (#9564)

Merge-train validated (tip 6ce4effef8). Vitest failures confirmed as base-red (#9679).
This commit is contained in:
backryun
2026-08-08 08:54:05 +09:00
committed by GitHub
parent 250ea5e849
commit c4f37ab01b
2 changed files with 5 additions and 3 deletions

View File

@@ -46,7 +46,7 @@ export function sanitizeChatRequestBody(
}
if (Array.isArray(body.tools)) {
body.tools = body.tools.filter((tool: Record<string, unknown>) => {
const tools = body.tools.filter((tool: Record<string, unknown>) => {
const toolType = typeof tool.type === "string" ? tool.type : "";
if (toolType && toolType !== "function" && !tool.function && tool.name === undefined) {
return true;
@@ -56,7 +56,7 @@ export function sanitizeChatRequestBody(
return name && String(name).trim().length > 0;
});
body.tools = body.tools.map((tool) => sanitizeOpenAITool(tool) as (typeof body.tools)[number]);
body.tools = tools.map((tool) => sanitizeOpenAITool(tool));
}
return body;

View File

@@ -49,6 +49,7 @@ test("sanitizeChatRequestBody: strips empty message name and filters nameless to
],
tools: [
{ type: "function", function: { name: "real_tool", parameters: {} } },
{ type: "web_search_preview" },
{ type: "function", function: { name: "" } }, // dropped — empty name
{ type: "function", function: {} }, // dropped — no name
],
@@ -62,8 +63,9 @@ test("sanitizeChatRequestBody: strips empty message name and filters nameless to
assert.equal(messages[1].name, "keepme", "non-empty name kept");
const tools = out.tools as Array<Record<string, unknown>>;
assert.equal(tools.length, 1, "only the named tool survives");
assert.equal(tools.length, 2, "the named function and built-in tool survive");
assert.equal((tools[0].function as Record<string, unknown>).name, "real_tool");
assert.deepEqual(tools[1], { type: "web_search_preview" });
});
test("checkIdempotencyCache returns { hit:null, idempotencyKey } on a miss", async () => {