diff --git a/src/agents/pi-tools.before-tool-call.e2e.test.ts b/src/agents/pi-tools.before-tool-call.e2e.test.ts index 4734ddeb32a..b615245bc3d 100644 --- a/src/agents/pi-tools.before-tool-call.e2e.test.ts +++ b/src/agents/pi-tools.before-tool-call.e2e.test.ts @@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { resetDiagnosticSessionStateForTest } from "../logging/diagnostic-session-state.js"; import { getGlobalHookRunner } from "../plugins/hook-runner-global.js"; import { toClientToolDefinitions, toToolDefinitions } from "./pi-tool-definition-adapter.js"; +import { wrapToolWithAbortSignal } from "./pi-tools.abort.js"; import { wrapToolWithBeforeToolCallHook } from "./pi-tools.before-tool-call.js"; vi.mock("../plugins/hook-runner-global.js"); @@ -162,6 +163,24 @@ describe("before_tool_call hook deduplication (#15502)", () => { expect(hookRunner.runBeforeToolCall).toHaveBeenCalledTimes(1); }); + + it("fires hook exactly once when tool goes through wrap + abort + toToolDefinitions", async () => { + const execute = vi.fn().mockResolvedValue({ content: [], details: { ok: true } }); + // oxlint-disable-next-line typescript/no-explicit-any + const baseTool = { name: "Bash", execute, description: "bash", parameters: {} } as any; + + const abortController = new AbortController(); + const wrapped = wrapToolWithBeforeToolCallHook(baseTool, { + agentId: "main", + sessionKey: "main", + }); + const withAbort = wrapToolWithAbortSignal(wrapped, abortController.signal); + const [def] = toToolDefinitions([withAbort]); + + await def.execute("call-abort-dedup", { command: "ls" }, undefined, undefined, undefined); + + expect(hookRunner.runBeforeToolCall).toHaveBeenCalledTimes(1); + }); }); describe("before_tool_call hook integration for client tools", () => { diff --git a/src/agents/pi-tools.before-tool-call.ts b/src/agents/pi-tools.before-tool-call.ts index 1198c813fc8..a0a5ca4cb11 100644 --- a/src/agents/pi-tools.before-tool-call.ts +++ b/src/agents/pi-tools.before-tool-call.ts @@ -227,7 +227,7 @@ export function wrapToolWithBeforeToolCallHook( }; Object.defineProperty(wrappedTool, BEFORE_TOOL_CALL_WRAPPED, { value: true, - enumerable: false, + enumerable: true, }); return wrappedTool; }