From c48b4471aa6b299f4011997a6ec7c7f2df5b2341 Mon Sep 17 00:00:00 2001 From: Vignesh Natarajan Date: Sat, 14 Feb 2026 19:18:16 -0800 Subject: [PATCH] test (gateway/agent): cover bare reset command routing --- src/gateway/server-methods/agent.test.ts | 63 +++++++++++++++++++ ...r.agent.gateway-server-agent-b.e2e.test.ts | 27 ++++++++ 2 files changed, 90 insertions(+) diff --git a/src/gateway/server-methods/agent.test.ts b/src/gateway/server-methods/agent.test.ts index 6ea54fcd7..6286e356d 100644 --- a/src/gateway/server-methods/agent.test.ts +++ b/src/gateway/server-methods/agent.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, vi } from "vitest"; import type { GatewayRequestContext } from "./types.js"; +import { BARE_SESSION_RESET_PROMPT } from "../../auto-reply/reply/session-reset-prompt.js"; import { agentHandlers } from "./agent.js"; const mocks = vi.hoisted(() => ({ @@ -7,6 +8,7 @@ const mocks = vi.hoisted(() => ({ updateSessionStore: vi.fn(), agentCommand: vi.fn(), registerAgentRunContext: vi.fn(), + sessionsResetHandler: vi.fn(), loadConfigReturn: {} as Record, })); @@ -54,6 +56,13 @@ vi.mock("../../infra/agent-events.js", () => ({ onAgentEvent: vi.fn(), })); +vi.mock("./sessions.js", () => ({ + sessionsHandlers: { + "sessions.reset": (...args: unknown[]) => + (mocks.sessionsResetHandler as (...args: unknown[]) => unknown)(...args), + }, +})); + vi.mock("../../sessions/send-policy.js", () => ({ resolveSendPolicy: () => "allow", })); @@ -273,4 +282,58 @@ describe("gateway agent handler", () => { expect(capturedStore?.["agent:main:work"]).toBeDefined(); expect(capturedStore?.["agent:main:MAIN"]).toBeUndefined(); }); + + it("handles bare /new by resetting the same session and sending reset greeting prompt", async () => { + mocks.sessionsResetHandler.mockImplementation( + async (opts: { + params: { key: string; reason: string }; + respond: (ok: boolean, payload?: unknown) => void; + }) => { + expect(opts.params.key).toBe("agent:main:main"); + expect(opts.params.reason).toBe("new"); + opts.respond(true, { + ok: true, + key: "agent:main:main", + entry: { sessionId: "reset-session-id" }, + }); + }, + ); + + mocks.loadSessionEntry.mockReturnValue({ + cfg: {}, + storePath: "/tmp/sessions.json", + entry: { + sessionId: "reset-session-id", + updatedAt: Date.now(), + }, + canonicalKey: "agent:main:main", + }); + mocks.updateSessionStore.mockResolvedValue(undefined); + mocks.agentCommand.mockResolvedValue({ + payloads: [{ text: "ok" }], + meta: { durationMs: 100 }, + }); + + const respond = vi.fn(); + await agentHandlers.agent({ + params: { + message: "/new", + sessionKey: "agent:main:main", + idempotencyKey: "test-idem-new", + }, + respond, + context: makeContext(), + req: { type: "req", id: "4", method: "agent" }, + client: null, + isWebchatConnect: () => false, + }); + + await vi.waitFor(() => expect(mocks.agentCommand).toHaveBeenCalled()); + expect(mocks.sessionsResetHandler).toHaveBeenCalledTimes(1); + const call = mocks.agentCommand.mock.calls.at(-1)?.[0] as + | { message?: string; sessionId?: string } + | undefined; + expect(call?.message).toBe(BARE_SESSION_RESET_PROMPT); + expect(call?.sessionId).toBe("reset-session-id"); + }); }); diff --git a/src/gateway/server.agent.gateway-server-agent-b.e2e.test.ts b/src/gateway/server.agent.gateway-server-agent-b.e2e.test.ts index b90ade36b..2bbe39ecf 100644 --- a/src/gateway/server.agent.gateway-server-agent-b.e2e.test.ts +++ b/src/gateway/server.agent.gateway-server-agent-b.e2e.test.ts @@ -6,6 +6,7 @@ import { WebSocket } from "ws"; import type { ChannelPlugin } from "../channels/plugins/types.js"; import type { PluginRegistry } from "../plugins/registry.js"; import { whatsappPlugin } from "../../extensions/whatsapp/src/channel.js"; +import { BARE_SESSION_RESET_PROMPT } from "../auto-reply/reply/session-reset-prompt.js"; import { emitAgentEvent, registerAgentRunContext } from "../infra/agent-events.js"; import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js"; import { setRegistry } from "./server.agent.gateway-server-agent.mocks.js"; @@ -261,6 +262,32 @@ describe("gateway server agent", () => { expect(typeof call.sessionId).toBe("string"); }); + test("agent routes bare /new through session reset before running greeting prompt", async () => { + await useTempSessionStorePath(); + await writeSessionStore({ + entries: { + main: { + sessionId: "sess-main-before-reset", + updatedAt: Date.now(), + }, + }, + }); + const spy = vi.mocked(agentCommand); + const callsBefore = spy.mock.calls.length; + const res = await rpcReq(ws, "agent", { + message: "/new", + sessionKey: "main", + idempotencyKey: "idem-agent-new", + }); + expect(res.ok).toBe(true); + + await vi.waitFor(() => expect(spy.mock.calls.length).toBeGreaterThan(callsBefore)); + const call = spy.mock.calls.at(-1)?.[0] as Record; + expect(call.message).toBe(BARE_SESSION_RESET_PROMPT); + expect(typeof call.sessionId).toBe("string"); + expect(call.sessionId).not.toBe("sess-main-before-reset"); + }); + test("agent ack response then final response", { timeout: 8000 }, async () => { const ackP = onceMessage( ws,