From b9cd557d1d6773abc4e1ddc22c4758b9ecda2c0c Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Thu, 16 Apr 2026 23:51:26 +0200 Subject: [PATCH] fix(agent): guard afterToolCall hook errors in finalization closes #3084 --- packages/agent/CHANGELOG.md | 4 ++++ packages/agent/src/agent-loop.ts | 39 ++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/agent/CHANGELOG.md b/packages/agent/CHANGELOG.md index 2d7226e0..5855835f 100644 --- a/packages/agent/CHANGELOG.md +++ b/packages/agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed parallel tool-call finalization to convert `afterToolCall` hook throws into error tool results instead of aborting the batch ([#3084](https://github.com/badlogic/pi-mono/issues/3084)) + ## [0.67.6] - 2026-04-16 ## [0.67.5] - 2026-04-16 diff --git a/packages/agent/src/agent-loop.ts b/packages/agent/src/agent-loop.ts index 586a1b7d..8482c5ce 100644 --- a/packages/agent/src/agent-loop.ts +++ b/packages/agent/src/agent-loop.ts @@ -571,23 +571,28 @@ async function finalizeExecutedToolCall( let isError = executed.isError; if (config.afterToolCall) { - const afterResult = await config.afterToolCall( - { - assistantMessage, - toolCall: prepared.toolCall, - args: prepared.args, - result, - isError, - context: currentContext, - }, - signal, - ); - if (afterResult) { - result = { - content: afterResult.content ?? result.content, - details: afterResult.details ?? result.details, - }; - isError = afterResult.isError ?? isError; + try { + const afterResult = await config.afterToolCall( + { + assistantMessage, + toolCall: prepared.toolCall, + args: prepared.args, + result, + isError, + context: currentContext, + }, + signal, + ); + if (afterResult) { + result = { + content: afterResult.content ?? result.content, + details: afterResult.details ?? result.details, + }; + isError = afterResult.isError ?? isError; + } + } catch (error) { + result = createErrorToolResult(error instanceof Error ? error.message : String(error)); + isError = true; } }