From eae0039aa4308c08bdb27829265cf141cb1b655a Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Wed, 22 Apr 2026 13:09:45 -0700 Subject: [PATCH] fix(hooks): use live memory-core config during dreaming runs --- extensions/memory-core/src/dreaming.test.ts | 87 +++++++++++++++++++++ extensions/memory-core/src/dreaming.ts | 3 +- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/extensions/memory-core/src/dreaming.test.ts b/extensions/memory-core/src/dreaming.test.ts index 30edd058400..d0a393f6447 100644 --- a/extensions/memory-core/src/dreaming.test.ts +++ b/extensions/memory-core/src/dreaming.test.ts @@ -1383,6 +1383,93 @@ describe("gateway startup reconciliation", () => { clearInternalHooks(); } }); + + it("uses live runtime config for the heartbeat dreaming run payload", async () => { + clearInternalHooks(); + const logger = createLogger(); + const harness = createCronHarness(); + const onMock = vi.fn(); + const workspaceDir = await createTempWorkspace("memory-dreaming-live-config-workspace-"); + const runtimeLoadConfig = vi.fn( + () => + ({ + agents: { + list: [{ id: "main", default: true, workspace: workspaceDir }], + }, + plugins: { + entries: { + "memory-core": { + config: { + dreaming: { + enabled: true, + frequency: "15 4 * * *", + timezone: "UTC", + limit: 0, + }, + }, + }, + }, + }, + }) as OpenClawConfig, + ); + const api: DreamingPluginApiTestDouble = { + config: { + plugins: { + entries: { + "memory-core": { + config: { + dreaming: { + enabled: true, + frequency: "15 4 * * *", + timezone: "UTC", + limit: 5, + }, + }, + }, + }, + }, + } as OpenClawConfig, + pluginConfig: {}, + logger, + runtime: { + config: { + loadConfig: runtimeLoadConfig, + }, + }, + on: onMock, + }; + + try { + registerShortTermPromotionDreamingForTest(api); + await triggerGatewayStart(onMock, { + config: api.config, + getCron: () => harness.cron, + }); + + const sessionKey = "agent:main:main"; + enqueueSystemEvent(constants.DREAMING_SYSTEM_EVENT_TEXT, { + sessionKey, + contextKey: "cron:memory-dreaming", + }); + + const beforeAgentReply = getBeforeAgentReplyHandler(onMock); + const result = await beforeAgentReply( + { cleanedBody: constants.DREAMING_SYSTEM_EVENT_TEXT }, + { trigger: "heartbeat", sessionKey }, + ); + + expect(result).toEqual({ + handled: true, + reason: "memory-core: short-term dreaming processed", + }); + expect(runtimeLoadConfig).toHaveBeenCalled(); + expect(logger.warn).not.toHaveBeenCalledWith( + "memory-core: dreaming promotion skipped because no memory workspace is available.", + ); + } finally { + clearInternalHooks(); + } + }); }); describe("short-term dreaming trigger", () => { diff --git a/extensions/memory-core/src/dreaming.ts b/extensions/memory-core/src/dreaming.ts index bb314ad10ce..25c65dd4cc6 100644 --- a/extensions/memory-core/src/dreaming.ts +++ b/extensions/memory-core/src/dreaming.ts @@ -736,6 +736,7 @@ export function registerShortTermPromotionDreaming(api: OpenClawPluginApi): void if (ctx.trigger !== "heartbeat") { return undefined; } + const currentConfig = resolveCurrentConfig(); const config = await reconcileManagedDreamingCron({ reason: "runtime", }); @@ -749,7 +750,7 @@ export function registerShortTermPromotionDreaming(api: OpenClawPluginApi): void cleanedBody: event.cleanedBody, trigger: ctx.trigger, workspaceDir: ctx.workspaceDir, - cfg: api.config, + cfg: currentConfig, config, logger: api.logger, subagent: config.enabled ? api.runtime?.subagent : undefined,