fix (agents): harden transcript tool-call block sanitization
This commit is contained in:
@@ -223,6 +223,32 @@ describe("sanitizeToolCallInputs", () => {
|
||||
expect(out.map((m) => m.role)).toEqual(["user"]);
|
||||
});
|
||||
|
||||
it("drops tool calls with missing or blank name/id", () => {
|
||||
const input: AgentMessage[] = [
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "toolCall", id: "call_ok", name: "read", arguments: {} },
|
||||
{ type: "toolCall", id: "call_empty_name", name: "", arguments: {} },
|
||||
{ type: "toolUse", id: "call_blank_name", name: " ", input: {} },
|
||||
{ type: "functionCall", id: "", name: "exec", arguments: {} },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const out = sanitizeToolCallInputs(input);
|
||||
const assistant = out[0] as Extract<AgentMessage, { role: "assistant" }>;
|
||||
const toolCalls = Array.isArray(assistant.content)
|
||||
? assistant.content.filter((block) => {
|
||||
const type = (block as { type?: unknown }).type;
|
||||
return typeof type === "string" && ["toolCall", "toolUse", "functionCall"].includes(type);
|
||||
})
|
||||
: [];
|
||||
|
||||
expect(toolCalls).toHaveLength(1);
|
||||
expect((toolCalls[0] as { id?: unknown }).id).toBe("call_ok");
|
||||
});
|
||||
|
||||
it("keeps valid tool calls and preserves text blocks", () => {
|
||||
const input: AgentMessage[] = [
|
||||
{
|
||||
|
||||
@@ -58,6 +58,18 @@ function hasToolCallInput(block: ToolCallBlock): boolean {
|
||||
return hasInput || hasArguments;
|
||||
}
|
||||
|
||||
function hasNonEmptyStringField(value: unknown): boolean {
|
||||
return typeof value === "string" && value.trim().length > 0;
|
||||
}
|
||||
|
||||
function hasToolCallId(block: ToolCallBlock): boolean {
|
||||
return hasNonEmptyStringField(block.id);
|
||||
}
|
||||
|
||||
function hasToolCallName(block: ToolCallBlock): boolean {
|
||||
return hasNonEmptyStringField(block.name);
|
||||
}
|
||||
|
||||
function extractToolResultId(msg: Extract<AgentMessage, { role: "toolResult" }>): string | null {
|
||||
const toolCallId = (msg as { toolCallId?: unknown }).toolCallId;
|
||||
if (typeof toolCallId === "string" && toolCallId) {
|
||||
@@ -118,7 +130,10 @@ export function repairToolCallInputs(messages: AgentMessage[]): ToolCallInputRep
|
||||
let droppedInMessage = 0;
|
||||
|
||||
for (const block of msg.content) {
|
||||
if (isToolCallBlock(block) && !hasToolCallInput(block)) {
|
||||
if (
|
||||
isToolCallBlock(block) &&
|
||||
(!hasToolCallInput(block) || !hasToolCallId(block) || !hasToolCallName(block))
|
||||
) {
|
||||
droppedToolCalls += 1;
|
||||
droppedInMessage += 1;
|
||||
changed = true;
|
||||
|
||||
Reference in New Issue
Block a user