refactor(agent): dedupe harness and command workflows

This commit is contained in:
Peter Steinberger
2026-02-16 14:52:09 +00:00
parent 04892ee230
commit f717a13039
204 changed files with 7366 additions and 11540 deletions

View File

@@ -25,6 +25,36 @@ vi.mock("./pi-tools.before-tool-call.js", () => ({
runBeforeToolCallHook: hookMocks.runBeforeToolCallHook,
}));
function createReadTool() {
return {
name: "read",
label: "Read",
description: "reads",
parameters: {},
execute: vi.fn(async () => ({ content: [], details: { ok: true } })),
} satisfies AgentTool<unknown, unknown>;
}
function enableAfterToolCallHook() {
hookMocks.runner.hasHooks.mockImplementation((name: string) => name === "after_tool_call");
}
async function executeReadTool(callId: string) {
const defs = toToolDefinitions([createReadTool()]);
return await defs[0].execute(callId, { path: "/tmp/file" }, undefined, undefined);
}
function expectReadAfterToolCallPayload(result: Awaited<ReturnType<typeof executeReadTool>>) {
expect(hookMocks.runner.runAfterToolCall).toHaveBeenCalledWith(
{
toolName: "read",
params: { mode: "safe" },
result,
},
{ toolName: "read" },
);
}
describe("pi tool definition adapter after_tool_call", () => {
beforeEach(() => {
hookMocks.runner.hasHooks.mockReset();
@@ -42,68 +72,31 @@ describe("pi tool definition adapter after_tool_call", () => {
});
it("dispatches after_tool_call once on successful adapter execution", async () => {
hookMocks.runner.hasHooks.mockImplementation((name: string) => name === "after_tool_call");
enableAfterToolCallHook();
hookMocks.runBeforeToolCallHook.mockResolvedValue({
blocked: false,
params: { mode: "safe" },
});
const tool = {
name: "read",
label: "Read",
description: "reads",
parameters: {},
execute: vi.fn(async () => ({ content: [], details: { ok: true } })),
} satisfies AgentTool<unknown, unknown>;
const defs = toToolDefinitions([tool]);
const result = await defs[0].execute("call-ok", { path: "/tmp/file" }, undefined, undefined);
const result = await executeReadTool("call-ok");
expect(result.details).toMatchObject({ ok: true });
expect(hookMocks.runner.runAfterToolCall).toHaveBeenCalledTimes(1);
expect(hookMocks.runner.runAfterToolCall).toHaveBeenCalledWith(
{
toolName: "read",
params: { mode: "safe" },
result,
},
{ toolName: "read" },
);
expectReadAfterToolCallPayload(result);
});
it("uses wrapped-tool adjusted params for after_tool_call payload", async () => {
hookMocks.runner.hasHooks.mockImplementation((name: string) => name === "after_tool_call");
enableAfterToolCallHook();
hookMocks.isToolWrappedWithBeforeToolCallHook.mockReturnValue(true);
hookMocks.consumeAdjustedParamsForToolCall.mockReturnValue({ mode: "safe" });
const tool = {
name: "read",
label: "Read",
description: "reads",
parameters: {},
execute: vi.fn(async () => ({ content: [], details: { ok: true } })),
} satisfies AgentTool<unknown, unknown>;
const defs = toToolDefinitions([tool]);
const result = await defs[0].execute(
"call-ok-wrapped",
{ path: "/tmp/file" },
undefined,
undefined,
);
const result = await executeReadTool("call-ok-wrapped");
expect(result.details).toMatchObject({ ok: true });
expect(hookMocks.runBeforeToolCallHook).not.toHaveBeenCalled();
expect(hookMocks.runner.runAfterToolCall).toHaveBeenCalledWith(
{
toolName: "read",
params: { mode: "safe" },
result,
},
{ toolName: "read" },
);
expectReadAfterToolCallPayload(result);
});
it("dispatches after_tool_call once on adapter error with normalized tool name", async () => {
hookMocks.runner.hasHooks.mockImplementation((name: string) => name === "after_tool_call");
enableAfterToolCallHook();
const tool = {
name: "bash",
label: "Bash",
@@ -134,18 +127,9 @@ describe("pi tool definition adapter after_tool_call", () => {
});
it("does not break execution when after_tool_call hook throws", async () => {
hookMocks.runner.hasHooks.mockImplementation((name: string) => name === "after_tool_call");
enableAfterToolCallHook();
hookMocks.runner.runAfterToolCall.mockRejectedValue(new Error("hook failed"));
const tool = {
name: "read",
label: "Read",
description: "reads",
parameters: {},
execute: vi.fn(async () => ({ content: [], details: { ok: true } })),
} satisfies AgentTool<unknown, unknown>;
const defs = toToolDefinitions([tool]);
const result = await defs[0].execute("call-ok2", { path: "/tmp/file" }, undefined, undefined);
const result = await executeReadTool("call-ok2");
expect(result.details).toMatchObject({ ok: true });
expect(hookMocks.runner.runAfterToolCall).toHaveBeenCalledTimes(1);