diff --git a/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts b/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts index d602b0a73f..caf9aff3f8 100644 --- a/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts +++ b/src/auto-reply/reply/agent-runner.misc.runreplyagent.test.ts @@ -8,7 +8,6 @@ import type { TemplateContext } from "../templating.js"; import type { FollowupRun, QueueSettings } from "./queue.js"; import { loadSessionStore, saveSessionStore } from "../../config/sessions.js"; import { onAgentEvent } from "../../infra/agent-events.js"; -import { DEFAULT_MEMORY_FLUSH_PROMPT } from "./memory-flush.js"; import { createMockTypingController } from "./test-helpers.js"; const runEmbeddedPiAgentMock = vi.fn(); @@ -948,7 +947,7 @@ describe("runReplyAgent fallback reasoning tags", () => { it("enforces during memory flush on fallback providers", async () => { runEmbeddedPiAgentMock.mockImplementation(async (params: EmbeddedPiAgentParams) => { - if (params.prompt === DEFAULT_MEMORY_FLUSH_PROMPT) { + if (params.prompt?.includes("Pre-compaction memory flush.")) { return { payloads: [], meta: {} }; } return { payloads: [{ text: "ok" }], meta: {} }; @@ -970,7 +969,9 @@ describe("runReplyAgent fallback reasoning tags", () => { const flushCall = runEmbeddedPiAgentMock.mock.calls.find( ([params]) => - (params as EmbeddedPiAgentParams | undefined)?.prompt === DEFAULT_MEMORY_FLUSH_PROMPT, + (params as EmbeddedPiAgentParams | undefined)?.prompt?.includes( + "Pre-compaction memory flush.", + ), )?.[0] as EmbeddedPiAgentParams | undefined; expect(flushCall?.enforceFinalTag).toBe(true); diff --git a/src/auto-reply/reply/agent-runner.runreplyagent.test.ts b/src/auto-reply/reply/agent-runner.runreplyagent.test.ts index ec7fb1161f..35d2447658 100644 --- a/src/auto-reply/reply/agent-runner.runreplyagent.test.ts +++ b/src/auto-reply/reply/agent-runner.runreplyagent.test.ts @@ -8,7 +8,6 @@ import type { TemplateContext } from "../templating.js"; import type { GetReplyOptions } from "../types.js"; import type { FollowupRun, QueueSettings } from "./queue.js"; import * as sessions from "../../config/sessions.js"; -import { DEFAULT_MEMORY_FLUSH_PROMPT } from "./memory-flush.js"; import { createMockTypingController } from "./test-helpers.js"; type AgentRunParams = { @@ -949,7 +948,7 @@ describe("runReplyAgent memory flush", () => { const calls: Array = []; state.runEmbeddedPiAgentMock.mockImplementation(async (params: EmbeddedRunParams) => { calls.push(params); - if (params.prompt === DEFAULT_MEMORY_FLUSH_PROMPT) { + if (params.prompt?.includes("Pre-compaction memory flush.")) { return { payloads: [], meta: {} }; } return { @@ -1009,7 +1008,7 @@ describe("runReplyAgent memory flush", () => { const calls: Array<{ prompt?: string }> = []; state.runEmbeddedPiAgentMock.mockImplementation(async (params: EmbeddedRunParams) => { calls.push({ prompt: params.prompt }); - if (params.prompt === DEFAULT_MEMORY_FLUSH_PROMPT) { + if (params.prompt?.includes("Pre-compaction memory flush.")) { return { payloads: [], meta: {} }; } return { @@ -1031,7 +1030,11 @@ describe("runReplyAgent memory flush", () => { commandBody: "hello", }); - expect(calls.map((call) => call.prompt)).toEqual([DEFAULT_MEMORY_FLUSH_PROMPT, "hello"]); + expect(calls).toHaveLength(2); + expect(calls[0]?.prompt).toContain("Pre-compaction memory flush."); + expect(calls[0]?.prompt).toContain("Current time:"); + expect(calls[0]?.prompt).toMatch(/memory\/\d{4}-\d{2}-\d{2}\.md/); + expect(calls[1]?.prompt).toBe("hello"); const stored = JSON.parse(await fs.readFile(storePath, "utf-8")); expect(stored[sessionKey].memoryFlushAt).toBeTypeOf("number"); @@ -1141,7 +1144,7 @@ describe("runReplyAgent memory flush", () => { await seedSessionStore({ storePath, sessionKey, entry: sessionEntry }); state.runEmbeddedPiAgentMock.mockImplementation(async (params: EmbeddedRunParams) => { - if (params.prompt === DEFAULT_MEMORY_FLUSH_PROMPT) { + if (params.prompt?.includes("Pre-compaction memory flush.")) { params.onAgentEvent?.({ stream: "compaction", data: { phase: "end", willRetry: false }, diff --git a/src/auto-reply/reply/memory-flush.test.ts b/src/auto-reply/reply/memory-flush.test.ts new file mode 100644 index 0000000000..362b1b10a2 --- /dev/null +++ b/src/auto-reply/reply/memory-flush.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from "vitest"; +import { resolveMemoryFlushPromptForRun } from "./memory-flush.js"; + +describe("resolveMemoryFlushPromptForRun", () => { + const cfg = { + agents: { + defaults: { + userTimezone: "America/New_York", + timeFormat: "12", + }, + }, + }; + + it("replaces YYYY-MM-DD using user timezone and appends current time", () => { + const prompt = resolveMemoryFlushPromptForRun({ + prompt: "Store durable notes in memory/YYYY-MM-DD.md", + cfg, + nowMs: Date.UTC(2026, 1, 16, 15, 0, 0), + }); + + expect(prompt).toContain("memory/2026-02-16.md"); + expect(prompt).toContain("Current time:"); + expect(prompt).toContain("(America/New_York)"); + }); + + it("does not append a duplicate current time line", () => { + const prompt = resolveMemoryFlushPromptForRun({ + prompt: "Store notes.\nCurrent time: already present", + cfg, + nowMs: Date.UTC(2026, 1, 16, 15, 0, 0), + }); + + expect(prompt).toContain("Current time: already present"); + expect((prompt.match(/Current time:/g) ?? []).length).toBe(1); + }); +});