Spaces:
Configuration error
Configuration error
melbot
/
src
/auto-reply
/reply
/agent-runner.memory-flush.runreplyagent-memory-flush.skips-memory-flush-cli-providers.test.ts
| import fs from "node:fs/promises"; | |
| import os from "node:os"; | |
| import path from "node:path"; | |
| import { describe, expect, it, vi } from "vitest"; | |
| import type { TemplateContext } from "../templating.js"; | |
| import type { FollowupRun, QueueSettings } from "./queue.js"; | |
| import { createMockTypingController } from "./test-helpers.js"; | |
| const runEmbeddedPiAgentMock = vi.fn(); | |
| const runCliAgentMock = vi.fn(); | |
| type EmbeddedRunParams = { | |
| prompt?: string; | |
| extraSystemPrompt?: string; | |
| onAgentEvent?: (evt: { stream?: string; data?: { phase?: string; willRetry?: boolean } }) => void; | |
| }; | |
| vi.mock("../../agents/model-fallback.js", () => ({ | |
| runWithModelFallback: async ({ | |
| provider, | |
| model, | |
| run, | |
| }: { | |
| provider: string; | |
| model: string; | |
| run: (provider: string, model: string) => Promise<unknown>; | |
| }) => ({ | |
| result: await run(provider, model), | |
| provider, | |
| model, | |
| }), | |
| })); | |
| vi.mock("../../agents/cli-runner.js", () => ({ | |
| runCliAgent: (params: unknown) => runCliAgentMock(params), | |
| })); | |
| vi.mock("../../agents/pi-embedded.js", () => ({ | |
| queueEmbeddedPiMessage: vi.fn().mockReturnValue(false), | |
| runEmbeddedPiAgent: (params: unknown) => runEmbeddedPiAgentMock(params), | |
| })); | |
| vi.mock("./queue.js", async () => { | |
| const actual = await vi.importActual<typeof import("./queue.js")>("./queue.js"); | |
| return { | |
| ...actual, | |
| enqueueFollowupRun: vi.fn(), | |
| scheduleFollowupDrain: vi.fn(), | |
| }; | |
| }); | |
| import { runReplyAgent } from "./agent-runner.js"; | |
| async function seedSessionStore(params: { | |
| storePath: string; | |
| sessionKey: string; | |
| entry: Record<string, unknown>; | |
| }) { | |
| await fs.mkdir(path.dirname(params.storePath), { recursive: true }); | |
| await fs.writeFile( | |
| params.storePath, | |
| JSON.stringify({ [params.sessionKey]: params.entry }, null, 2), | |
| "utf-8", | |
| ); | |
| } | |
| function createBaseRun(params: { | |
| storePath: string; | |
| sessionEntry: Record<string, unknown>; | |
| config?: Record<string, unknown>; | |
| runOverrides?: Partial<FollowupRun["run"]>; | |
| }) { | |
| const typing = createMockTypingController(); | |
| const sessionCtx = { | |
| Provider: "whatsapp", | |
| OriginatingTo: "+15550001111", | |
| AccountId: "primary", | |
| MessageSid: "msg", | |
| } as unknown as TemplateContext; | |
| const resolvedQueue = { mode: "interrupt" } as unknown as QueueSettings; | |
| const followupRun = { | |
| prompt: "hello", | |
| summaryLine: "hello", | |
| enqueuedAt: Date.now(), | |
| run: { | |
| agentId: "main", | |
| agentDir: "/tmp/agent", | |
| sessionId: "session", | |
| sessionKey: "main", | |
| messageProvider: "whatsapp", | |
| sessionFile: "/tmp/session.jsonl", | |
| workspaceDir: "/tmp", | |
| config: params.config ?? {}, | |
| skillsSnapshot: {}, | |
| provider: "anthropic", | |
| model: "claude", | |
| thinkLevel: "low", | |
| verboseLevel: "off", | |
| elevatedLevel: "off", | |
| bashElevated: { | |
| enabled: false, | |
| allowed: false, | |
| defaultLevel: "off", | |
| }, | |
| timeoutMs: 1_000, | |
| blockReplyBreak: "message_end", | |
| }, | |
| } as unknown as FollowupRun; | |
| const run = { | |
| ...followupRun.run, | |
| ...params.runOverrides, | |
| config: params.config ?? followupRun.run.config, | |
| }; | |
| return { | |
| typing, | |
| sessionCtx, | |
| resolvedQueue, | |
| followupRun: { ...followupRun, run }, | |
| }; | |
| } | |
| describe("runReplyAgent memory flush", () => { | |
| it("skips memory flush for CLI providers", async () => { | |
| runEmbeddedPiAgentMock.mockReset(); | |
| runCliAgentMock.mockReset(); | |
| const tmp = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-flush-")); | |
| const storePath = path.join(tmp, "sessions.json"); | |
| const sessionKey = "main"; | |
| const sessionEntry = { | |
| sessionId: "session", | |
| updatedAt: Date.now(), | |
| totalTokens: 80_000, | |
| compactionCount: 1, | |
| }; | |
| await seedSessionStore({ storePath, sessionKey, entry: sessionEntry }); | |
| const calls: Array<{ prompt?: string }> = []; | |
| runEmbeddedPiAgentMock.mockImplementation(async (params: EmbeddedRunParams) => { | |
| calls.push({ prompt: params.prompt }); | |
| return { | |
| payloads: [{ text: "ok" }], | |
| meta: { agentMeta: { usage: { input: 1, output: 1 } } }, | |
| }; | |
| }); | |
| runCliAgentMock.mockResolvedValue({ | |
| payloads: [{ text: "ok" }], | |
| meta: { agentMeta: { usage: { input: 1, output: 1 } } }, | |
| }); | |
| const { typing, sessionCtx, resolvedQueue, followupRun } = createBaseRun({ | |
| storePath, | |
| sessionEntry, | |
| runOverrides: { provider: "codex-cli" }, | |
| }); | |
| await runReplyAgent({ | |
| commandBody: "hello", | |
| followupRun, | |
| queueKey: "main", | |
| resolvedQueue, | |
| shouldSteer: false, | |
| shouldFollowup: false, | |
| isActive: false, | |
| isStreaming: false, | |
| typing, | |
| sessionCtx, | |
| sessionEntry, | |
| sessionStore: { [sessionKey]: sessionEntry }, | |
| sessionKey, | |
| storePath, | |
| defaultModel: "anthropic/claude-opus-4-5", | |
| agentCfgContextTokens: 100_000, | |
| resolvedVerboseLevel: "off", | |
| isNewSession: false, | |
| blockStreamingEnabled: false, | |
| resolvedBlockStreamingBreak: "message_end", | |
| shouldInjectGroupIntro: false, | |
| typingMode: "instant", | |
| }); | |
| expect(runCliAgentMock).toHaveBeenCalledTimes(1); | |
| const call = runCliAgentMock.mock.calls[0]?.[0] as { prompt?: string } | undefined; | |
| expect(call?.prompt).toBe("hello"); | |
| expect(runEmbeddedPiAgentMock).not.toHaveBeenCalled(); | |
| }); | |
| }); | |