import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import type { HookRunner } from "../../plugins/hooks.js"; import type { HandleCommandsParams } from "./commands-types.js"; const hookRunnerMocks = vi.hoisted(() => ({ hasHooks: vi.fn(), runBeforeReset: vi.fn(), })); vi.mock("../../plugins/hook-runner-global.js", () => ({ getGlobalHookRunner: () => ({ hasHooks: hookRunnerMocks.hasHooks, runBeforeReset: hookRunnerMocks.runBeforeReset, }) as unknown as HookRunner, })); const { emitResetCommandHooks } = await import("./commands-core.js"); describe("emitResetCommandHooks", () => { async function runBeforeResetContext(sessionKey?: string) { const command = { surface: "discord", senderId: "rai", channel: "discord", from: "discord:rai", to: "discord:bot", resetHookTriggered: false, } as HandleCommandsParams["command"]; await emitResetCommandHooks({ action: "new", ctx: {} as HandleCommandsParams["ctx"], cfg: {} as HandleCommandsParams["cfg"], command, sessionKey, previousSessionEntry: { sessionId: "prev-session", } as HandleCommandsParams["previousSessionEntry"], workspaceDir: "/tmp/openclaw-workspace", }); await vi.waitFor(() => expect(hookRunnerMocks.runBeforeReset).toHaveBeenCalledTimes(1)); const [, ctx] = hookRunnerMocks.runBeforeReset.mock.calls[0] ?? []; return ctx; } beforeEach(() => { hookRunnerMocks.hasHooks.mockReset(); hookRunnerMocks.runBeforeReset.mockReset(); hookRunnerMocks.hasHooks.mockImplementation((hookName) => hookName === "before_reset"); hookRunnerMocks.runBeforeReset.mockResolvedValue(undefined); }); afterEach(() => { vi.restoreAllMocks(); }); it("passes the bound agent id to before_reset hooks for multi-agent session keys", async () => { const ctx = await runBeforeResetContext("agent:navi:main"); expect(ctx).toMatchObject({ agentId: "navi", sessionKey: "agent:navi:main", sessionId: "prev-session", workspaceDir: "/tmp/openclaw-workspace", }); }); it("falls back to main when the reset hook has no session key", async () => { const ctx = await runBeforeResetContext(undefined); expect(ctx).toMatchObject({ agentId: "main", sessionKey: undefined, sessionId: "prev-session", workspaceDir: "/tmp/openclaw-workspace", }); }); it("keeps the main-agent path on the main agent workspace", async () => { const ctx = await runBeforeResetContext("agent:main:main"); expect(ctx).toMatchObject({ agentId: "main", sessionKey: "agent:main:main", sessionId: "prev-session", workspaceDir: "/tmp/openclaw-workspace", }); }); });