fix(agents): clear orphan tool state on string assistant turns

This commit is contained in:
Ayaan Zaidi
2026-05-30 09:40:11 +05:30
parent 56fc17be78
commit 72eff6b2e9
2 changed files with 31 additions and 4 deletions

View File

@@ -185,13 +185,13 @@ async function jsonlFileHasOrphanedTrailingToolUse(filePath: string): Promise<bo
}
const message = rec?.message as Record<string, unknown> | undefined;
const role = message?.role;
const blocks = toToolContentBlocks(message?.content);
if (!blocks) {
continue;
}
if (role === "assistant") {
lastAssistantToolUseIds = new Set();
answeredToolResultIds = new Set();
const blocks = toToolContentBlocks(message?.content);
if (!blocks) {
continue;
}
for (const block of blocks) {
if (isClaudeTranscriptToolUseBlock(block)) {
const id = resolveToolUseId(block);
@@ -206,6 +206,10 @@ async function jsonlFileHasOrphanedTrailingToolUse(filePath: string): Promise<bo
}
}
} else if (role === "user") {
const blocks = toToolContentBlocks(message?.content);
if (!blocks) {
continue;
}
for (const block of blocks) {
if (isClaudeTranscriptToolResultBlock(block)) {
const id = resolveToolUseId(block);

View File

@@ -934,6 +934,29 @@ describe("claudeCliSessionTranscriptHasOrphanedToolUse", () => {
).toBe(false);
});
it("returns false when a later string assistant message supersedes an old orphan", async () => {
await writeJsonlSession("buried-string", [
{
type: "assistant",
message: {
role: "assistant",
content: [{ type: "tool_use", id: "toolu_old_string", name: "Bash", input: {} }],
},
},
{
type: "assistant",
message: { role: "assistant", content: "moving on" },
},
]);
expect(
await claudeCliSessionTranscriptHasOrphanedToolUse({
sessionId: "buried-string",
workspaceDir,
homeDir: tmpDir,
}),
).toBe(false);
});
it("rejects path-like session ids instead of escaping the Claude projects tree", async () => {
await writeJsonlSession("safe", []);
expect(