From d11613999a274e96af504e1eeff365240593dfef Mon Sep 17 00:00:00 2001 From: Enoch Date: Thu, 7 May 2026 20:45:27 +0800 Subject: [PATCH] fix tool execute after hook boundary --- src/plugin/tool-execute-after.test.ts | 26 +++++++++++++++++++++++++- src/plugin/tool-execute-after.ts | 11 ++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/plugin/tool-execute-after.test.ts b/src/plugin/tool-execute-after.test.ts index f6b55eea2..a7febd276 100644 --- a/src/plugin/tool-execute-after.test.ts +++ b/src/plugin/tool-execute-after.test.ts @@ -92,7 +92,6 @@ describe("createToolExecuteAfterHandler", () => { expect(output.title).toBe("stored title") expect(output.metadata).toEqual({ sessionId: "ses_native", agent: "hephaestus" }) }) - it("#given native session linkage without model #when stored metadata exists #then required task metadata is preserved", async () => { // given const model = { providerID: "openai", modelID: "gpt-5.5" } @@ -122,4 +121,29 @@ describe("createToolExecuteAfterHandler", () => { expect(output.title).toBe("stored title") expect(output.metadata).toEqual({ sessionId: "ses_native", agent: "hephaestus", model }) }) + + it("#given a non-extract hook throws #when tool.execute.after runs #then the handler absorbs the failure", async () => { + // given + const handler = createToolExecuteAfterHandler({ + ctx: { directory: "/repo" } as never, + hooks: { + directoryAgentsInjector: { + "tool.execute.after": async () => { + throw new TypeError("output output is undefined") + }, + }, + } as never, + }) + + const output = { title: "result", output: "read output", metadata: {} } + + // when + await handler( + { tool: "read", sessionID: "ses_parent", callID: "call_read" }, + output + ) + + // then + expect(output).toEqual({ title: "result", output: "read output", metadata: {} }) + }) }) diff --git a/src/plugin/tool-execute-after.ts b/src/plugin/tool-execute-after.ts index 7cfeb65b4..10bf8547a 100644 --- a/src/plugin/tool-execute-after.ts +++ b/src/plugin/tool-execute-after.ts @@ -182,6 +182,15 @@ export function createToolExecuteAfterHandler(args: { return } - await runToolExecuteAfterHooks() + try { + await runToolExecuteAfterHooks() + } catch (error) { + log("[tool-execute-after] Failed to process hooks", { + tool: input.tool, + sessionID: input.sessionID, + callID: input.callID ?? input.callId ?? input.call_id, + error, + }) + } } }