fix(agents): harden tool-name normalization and transcript repair

Landed from contributor PRs #30620 and #30735 by @Sid-Qin, plus #30881 by @liuxiaopai-ai.

Co-authored-by: SidQin-cyber <sidqin0410@gmail.com>
Co-authored-by: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-03-01 23:51:43 +00:00
parent 50e2674dfc
commit ee03ade0d6
7 changed files with 224 additions and 13 deletions

View File

@@ -31,6 +31,42 @@ function capToolResultSize(msg: AgentMessage): AgentMessage {
});
}
function trimNonEmptyString(value: unknown): string | undefined {
if (typeof value !== "string") {
return undefined;
}
const trimmed = value.trim();
return trimmed || undefined;
}
function normalizePersistedToolResultName(
message: AgentMessage,
fallbackName?: string,
): AgentMessage {
if ((message as { role?: unknown }).role !== "toolResult") {
return message;
}
const toolResult = message as Extract<AgentMessage, { role: "toolResult" }>;
const rawToolName = (toolResult as { toolName?: unknown }).toolName;
const normalizedToolName = trimNonEmptyString(rawToolName);
if (normalizedToolName) {
if (rawToolName === normalizedToolName) {
return toolResult;
}
return { ...toolResult, toolName: normalizedToolName };
}
const normalizedFallback = trimNonEmptyString(fallbackName);
if (normalizedFallback) {
return { ...toolResult, toolName: normalizedFallback };
}
if (typeof rawToolName === "string") {
return { ...toolResult, toolName: "unknown" };
}
return toolResult;
}
export function installSessionToolResultGuard(
sessionManager: SessionManager,
opts?: {
@@ -150,9 +186,10 @@ export function installSessionToolResultGuard(
if (id) {
pending.delete(id);
}
const normalizedToolResult = normalizePersistedToolResultName(nextMessage, toolName);
// Apply hard size cap before persistence to prevent oversized tool results
// from consuming the entire context window on subsequent LLM calls.
const capped = capToolResultSize(persistMessage(nextMessage));
const capped = capToolResultSize(persistMessage(normalizedToolResult));
const persisted = applyBeforeWriteHook(
persistToolResult(capped, {
toolCallId: id ?? undefined,