diff --git a/src/auto-reply/reply/agent-runner-memory.ts b/src/auto-reply/reply/agent-runner-memory.ts index 22c489c535..de81ffec66 100644 --- a/src/auto-reply/reply/agent-runner-memory.ts +++ b/src/auto-reply/reply/agent-runner-memory.ts @@ -19,6 +19,7 @@ import { registerAgentRunContext } from "../../infra/agent-events.js"; import { buildThreadingToolContext, resolveEnforceFinalTag } from "./agent-runner-utils.js"; import { resolveMemoryFlushContextWindowTokens, + resolveMemoryFlushPromptForRun, resolveMemoryFlushSettings, shouldRunMemoryFlush, } from "./memory-flush.js"; @@ -133,7 +134,10 @@ export async function runMemoryFlushIfNeeded(params: { agentDir: params.followupRun.run.agentDir, config: params.followupRun.run.config, skillsSnapshot: params.followupRun.run.skillsSnapshot, - prompt: memoryFlushSettings.prompt, + prompt: resolveMemoryFlushPromptForRun({ + prompt: memoryFlushSettings.prompt, + cfg: params.cfg, + }), extraSystemPrompt: flushSystemPrompt, ownerNumbers: params.followupRun.run.ownerNumbers, enforceFinalTag: resolveEnforceFinalTag(params.followupRun.run, provider), diff --git a/src/auto-reply/reply/memory-flush.ts b/src/auto-reply/reply/memory-flush.ts index 8ff6f1b1b6..a3b50ae344 100644 --- a/src/auto-reply/reply/memory-flush.ts +++ b/src/auto-reply/reply/memory-flush.ts @@ -1,5 +1,6 @@ import type { OpenClawConfig } from "../../config/config.js"; import { lookupContextTokens } from "../../agents/context.js"; +import { resolveCronStyleNow } from "../../agents/current-time.js"; import { DEFAULT_CONTEXT_TOKENS } from "../../agents/defaults.js"; import { DEFAULT_PI_COMPACTION_RESERVE_TOKENS_FLOOR } from "../../agents/pi-settings.js"; import { resolveFreshSessionTotalTokens, type SessionEntry } from "../../config/sessions.js"; @@ -20,6 +21,40 @@ export const DEFAULT_MEMORY_FLUSH_SYSTEM_PROMPT = [ `You may reply, but usually ${SILENT_REPLY_TOKEN} is correct.`, ].join(" "); +function formatDateStampInTimezone(nowMs: number, timezone: string): string { + const parts = new Intl.DateTimeFormat("en-US", { + timeZone: timezone, + year: "numeric", + month: "2-digit", + day: "2-digit", + }).formatToParts(new Date(nowMs)); + const year = parts.find((part) => part.type === "year")?.value; + const month = parts.find((part) => part.type === "month")?.value; + const day = parts.find((part) => part.type === "day")?.value; + if (year && month && day) { + return `${year}-${month}-${day}`; + } + return new Date(nowMs).toISOString().slice(0, 10); +} + +export function resolveMemoryFlushPromptForRun(params: { + prompt: string; + cfg?: OpenClawConfig; + nowMs?: number; +}): string { + const nowMs = Number.isFinite(params.nowMs) ? (params.nowMs as number) : Date.now(); + const { userTimezone, timeLine } = resolveCronStyleNow(params.cfg ?? {}, nowMs); + const dateStamp = formatDateStampInTimezone(nowMs, userTimezone); + const withDate = params.prompt.replaceAll("YYYY-MM-DD", dateStamp).trimEnd(); + if (!withDate) { + return timeLine; + } + if (withDate.includes("Current time:")) { + return withDate; + } + return `${withDate}\n${timeLine}`; +} + export type MemoryFlushSettings = { enabled: boolean; softThresholdTokens: number;