File size: 2,934 Bytes
fcd8223 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import { beforeEach, describe, expect, it, vi } from "vitest";
import {
buildHandledBeforeAgentReplyPayloads,
runBeforeAgentReplyForTurn,
withBeforeAgentReplyObserver,
} from "./before-agent-reply.js";
const hookRunner = vi.hoisted(() => ({
hasHooks: vi.fn(),
runBeforeAgentReply: vi.fn(),
}));
vi.mock("./hook-runner-global.js", () => ({
getGlobalHookRunner: () => hookRunner,
}));
function runHook(runId: string) {
return runBeforeAgentReplyForTurn({
runId,
trigger: "user",
event: { cleanedBody: runId },
context: { runId, trigger: "user" },
});
}
describe("before_agent_reply runner boundary", () => {
beforeEach(() => {
hookRunner.hasHooks.mockReset().mockReturnValue(true);
hookRunner.runBeforeAgentReply.mockReset().mockResolvedValue(undefined);
});
it("preserves the complete reply payload", () => {
const reply = {
text: "claimed",
channelData: { native: true },
sensitiveMedia: true,
videoAsNote: true,
};
expect(buildHandledBeforeAgentReplyPayloads(reply)).toEqual([reply]);
});
it.each([
{ runId: "missing", context: { runId: "missing" } },
{ runId: "mismatch", context: { runId: "mismatch", trigger: "heartbeat" } },
])("uses the validated turn trigger when context is $runId", async ({ runId, context }) => {
await runBeforeAgentReplyForTurn({
runId,
trigger: "user",
event: { cleanedBody: runId },
context,
});
const expectedContext = { ...context, trigger: "user" };
expect(hookRunner.hasHooks).toHaveBeenCalledWith("before_agent_reply", expectedContext);
expect(hookRunner.runBeforeAgentReply).toHaveBeenCalledWith(
{ cleanedBody: runId },
expectedContext,
);
});
it.each(["manual", "memory", "overflow"] as const)(
"does not dispatch for the internal %s trigger",
async (trigger) => {
await expect(
runBeforeAgentReplyForTurn({
runId: trigger,
trigger,
event: { cleanedBody: trigger },
context: { runId: trigger, trigger },
}),
).resolves.toBeUndefined();
expect(hookRunner.hasHooks).not.toHaveBeenCalled();
expect(hookRunner.runBeforeAgentReply).not.toHaveBeenCalled();
},
);
it("keeps a nested run from checkpointing its parent admission", async () => {
const beforeDispatch = vi.fn(async () => undefined);
const afterDispatch = vi.fn(async (result) => result);
hookRunner.runBeforeAgentReply.mockImplementation(async (_event, context) => {
if (context.runId === "parent") {
await runHook("child");
}
return undefined;
});
await withBeforeAgentReplyObserver({ beforeDispatch, afterDispatch }, () => runHook("parent"));
expect(hookRunner.runBeforeAgentReply).toHaveBeenCalledTimes(2);
expect(beforeDispatch).toHaveBeenCalledOnce();
expect(afterDispatch).toHaveBeenCalledOnce();
});
});
|