From f6ee2877e05254d73f2224025266461b7b1cdade Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 27 Apr 2026 11:19:00 +0100 Subject: [PATCH] refactor: share memory dreaming cron constants --- extensions/memory-core/src/dreaming.ts | 18 +++++------ ...-payload-migration.constants-drift.test.ts | 32 +++++-------------- .../doctor-cron-dreaming-payload-migration.ts | 22 ++++++------- src/memory-host-sdk/dreaming.ts | 10 ++++++ 4 files changed, 37 insertions(+), 45 deletions(-) diff --git a/extensions/memory-core/src/dreaming.ts b/extensions/memory-core/src/dreaming.ts index de1eb27cf74..89a2f797281 100644 --- a/extensions/memory-core/src/dreaming.ts +++ b/extensions/memory-core/src/dreaming.ts @@ -7,6 +7,15 @@ import { DEFAULT_MEMORY_DEEP_DREAMING_MIN_SCORE as DEFAULT_MEMORY_DREAMING_MIN_SCORE, DEFAULT_MEMORY_DEEP_DREAMING_MIN_UNIQUE_QUERIES as DEFAULT_MEMORY_DREAMING_MIN_UNIQUE_QUERIES, DEFAULT_MEMORY_DEEP_DREAMING_RECENCY_HALF_LIFE_DAYS as DEFAULT_MEMORY_DREAMING_RECENCY_HALF_LIFE_DAYS, + LEGACY_MEMORY_LIGHT_DREAMING_CRON_NAME as LEGACY_LIGHT_SLEEP_CRON_NAME, + LEGACY_MEMORY_LIGHT_DREAMING_CRON_TAG as LEGACY_LIGHT_SLEEP_CRON_TAG, + LEGACY_MEMORY_LIGHT_DREAMING_EVENT_TEXT as LEGACY_LIGHT_SLEEP_EVENT_TEXT, + LEGACY_MEMORY_REM_DREAMING_CRON_NAME as LEGACY_REM_SLEEP_CRON_NAME, + LEGACY_MEMORY_REM_DREAMING_CRON_TAG as LEGACY_REM_SLEEP_CRON_TAG, + LEGACY_MEMORY_REM_DREAMING_EVENT_TEXT as LEGACY_REM_SLEEP_EVENT_TEXT, + MANAGED_MEMORY_DREAMING_CRON_NAME as MANAGED_DREAMING_CRON_NAME, + MANAGED_MEMORY_DREAMING_CRON_TAG as MANAGED_DREAMING_CRON_TAG, + MEMORY_DREAMING_SYSTEM_EVENT_TEXT as DREAMING_SYSTEM_EVENT_TEXT, resolveMemoryCorePluginConfig, resolveMemoryDeepDreamingConfig, resolveMemoryDreamingWorkspaces, @@ -26,15 +35,6 @@ import { rankShortTermPromotionCandidates, } from "./short-term-promotion.js"; -const MANAGED_DREAMING_CRON_NAME = "Memory Dreaming Promotion"; -const MANAGED_DREAMING_CRON_TAG = "[managed-by=memory-core.short-term-promotion]"; -const DREAMING_SYSTEM_EVENT_TEXT = "__openclaw_memory_core_short_term_promotion_dream__"; -const LEGACY_LIGHT_SLEEP_CRON_NAME = "Memory Light Dreaming"; -const LEGACY_LIGHT_SLEEP_CRON_TAG = "[managed-by=memory-core.dreaming.light]"; -const LEGACY_LIGHT_SLEEP_EVENT_TEXT = "__openclaw_memory_core_light_sleep__"; -const LEGACY_REM_SLEEP_CRON_NAME = "Memory REM Dreaming"; -const LEGACY_REM_SLEEP_CRON_TAG = "[managed-by=memory-core.dreaming.rem]"; -const LEGACY_REM_SLEEP_EVENT_TEXT = "__openclaw_memory_core_rem_sleep__"; const RUNTIME_CRON_RECONCILE_INTERVAL_MS = 60_000; const HEARTBEAT_ISOLATED_SESSION_SUFFIX = ":heartbeat"; diff --git a/src/commands/doctor-cron-dreaming-payload-migration.constants-drift.test.ts b/src/commands/doctor-cron-dreaming-payload-migration.constants-drift.test.ts index 820460bb5b0..b09df91391f 100644 --- a/src/commands/doctor-cron-dreaming-payload-migration.constants-drift.test.ts +++ b/src/commands/doctor-cron-dreaming-payload-migration.constants-drift.test.ts @@ -2,27 +2,13 @@ import fs from "node:fs/promises"; import path from "node:path"; import { describe, expect, it } from "vitest"; -// Mirrored constants in src/commands/doctor-cron-dreaming-payload-migration.ts -// must match the source-of-truth values in -// extensions/memory-core/src/dreaming.ts. There is no shared module today -// because src/ does not import from extensions/, so this drift check stands -// in for that boundary: rename either side without updating the other and -// this test fails before the doctor migration silently stops matching jobs. const MIRROR_PATH = path.resolve(__dirname, "doctor-cron-dreaming-payload-migration.ts"); -const SOURCE_PATH = path.resolve( - __dirname, - "..", - "..", - "extensions", - "memory-core", - "src", - "dreaming.ts", -); +const SOURCE_PATH = path.resolve(__dirname, "..", "..", "src", "memory-host-sdk", "dreaming.ts"); const NAMES = [ - "MANAGED_DREAMING_CRON_NAME", - "MANAGED_DREAMING_CRON_TAG", - "DREAMING_SYSTEM_EVENT_TEXT", + "MANAGED_MEMORY_DREAMING_CRON_NAME", + "MANAGED_MEMORY_DREAMING_CRON_TAG", + "MEMORY_DREAMING_SYSTEM_EVENT_TEXT", ] as const; function extractStringConst(source: string, name: string): string { @@ -35,19 +21,17 @@ function extractStringConst(source: string, name: string): string { } describe("dreaming payload-migration constants drift", () => { - it("matches the source-of-truth values from extensions/memory-core/src/dreaming.ts", async () => { + it("imports the source-of-truth values from the memory host SDK", async () => { const [mirror, source] = await Promise.all([ fs.readFile(MIRROR_PATH, "utf-8"), fs.readFile(SOURCE_PATH, "utf-8"), ]); for (const name of NAMES) { - const mirrorValue = extractStringConst(mirror, name); const sourceValue = extractStringConst(source, name); - expect( - mirrorValue, - `${name} drift: mirror in src/commands does not match extensions/memory-core/src/dreaming.ts`, - ).toBe(sourceValue); + expect(sourceValue).toBeTruthy(); + expect(mirror).toContain(name); + expect(mirror).not.toMatch(new RegExp(`\\bconst ${name}\\b`)); } }); }); diff --git a/src/commands/doctor-cron-dreaming-payload-migration.ts b/src/commands/doctor-cron-dreaming-payload-migration.ts index 98f740dfa66..64bb58874ae 100644 --- a/src/commands/doctor-cron-dreaming-payload-migration.ts +++ b/src/commands/doctor-cron-dreaming-payload-migration.ts @@ -1,33 +1,31 @@ +import { + MANAGED_MEMORY_DREAMING_CRON_NAME, + MANAGED_MEMORY_DREAMING_CRON_TAG, + MEMORY_DREAMING_SYSTEM_EVENT_TEXT, +} from "../memory-host-sdk/dreaming.js"; import { normalizeOptionalLowercaseString, normalizeOptionalString, } from "../shared/string-coerce.js"; -// Constants are owned by the memory-core dreaming implementation. Mirrored here -// so doctor can rewrite stale jobs without taking a runtime dep on the -// extension. Keep in sync if the memory-core constants change. -const MANAGED_DREAMING_CRON_NAME = "Memory Dreaming Promotion"; -const MANAGED_DREAMING_CRON_TAG = "[managed-by=memory-core.short-term-promotion]"; -const DREAMING_SYSTEM_EVENT_TEXT = "__openclaw_memory_core_short_term_promotion_dream__"; - type UnknownRecord = Record; function isManagedDreamingJob(raw: UnknownRecord): boolean { const description = normalizeOptionalString(raw.description); - if (description?.includes(MANAGED_DREAMING_CRON_TAG)) { + if (description?.includes(MANAGED_MEMORY_DREAMING_CRON_TAG)) { return true; } const name = normalizeOptionalString(raw.name); - if (name !== MANAGED_DREAMING_CRON_NAME) { + if (name !== MANAGED_MEMORY_DREAMING_CRON_NAME) { return false; } const payload = (raw.payload as UnknownRecord | undefined) ?? undefined; const payloadKind = normalizeOptionalLowercaseString(payload?.kind); if (payloadKind === "systemevent") { - return normalizeOptionalString(payload?.text) === DREAMING_SYSTEM_EVENT_TEXT; + return normalizeOptionalString(payload?.text) === MEMORY_DREAMING_SYSTEM_EVENT_TEXT; } if (payloadKind === "agentturn") { - return normalizeOptionalString(payload?.message) === DREAMING_SYSTEM_EVENT_TEXT; + return normalizeOptionalString(payload?.message) === MEMORY_DREAMING_SYSTEM_EVENT_TEXT; } return false; } @@ -57,7 +55,7 @@ function rewriteDreamingJobShape(raw: UnknownRecord): void { raw.sessionTarget = "isolated"; raw.payload = { kind: "agentTurn", - message: DREAMING_SYSTEM_EVENT_TEXT, + message: MEMORY_DREAMING_SYSTEM_EVENT_TEXT, lightContext: true, }; raw.delivery = { mode: "none" }; diff --git a/src/memory-host-sdk/dreaming.ts b/src/memory-host-sdk/dreaming.ts index fb09b941c25..aade0337066 100644 --- a/src/memory-host-sdk/dreaming.ts +++ b/src/memory-host-sdk/dreaming.ts @@ -16,6 +16,16 @@ export const DEFAULT_MEMORY_DREAMING_STORAGE_MODE = "separate"; export const DEFAULT_MEMORY_DREAMING_SEPARATE_REPORTS = false; export const DEFAULT_MEMORY_DREAMING_FREQUENCY = "0 3 * * *"; export const DEFAULT_MEMORY_DREAMING_PLUGIN_ID = "memory-core"; +export const MANAGED_MEMORY_DREAMING_CRON_NAME = "Memory Dreaming Promotion"; +export const MANAGED_MEMORY_DREAMING_CRON_TAG = "[managed-by=memory-core.short-term-promotion]"; +export const MEMORY_DREAMING_SYSTEM_EVENT_TEXT = + "__openclaw_memory_core_short_term_promotion_dream__"; +export const LEGACY_MEMORY_LIGHT_DREAMING_CRON_NAME = "Memory Light Dreaming"; +export const LEGACY_MEMORY_LIGHT_DREAMING_CRON_TAG = "[managed-by=memory-core.dreaming.light]"; +export const LEGACY_MEMORY_LIGHT_DREAMING_EVENT_TEXT = "__openclaw_memory_core_light_sleep__"; +export const LEGACY_MEMORY_REM_DREAMING_CRON_NAME = "Memory REM Dreaming"; +export const LEGACY_MEMORY_REM_DREAMING_CRON_TAG = "[managed-by=memory-core.dreaming.rem]"; +export const LEGACY_MEMORY_REM_DREAMING_EVENT_TEXT = "__openclaw_memory_core_rem_sleep__"; export const DEFAULT_MEMORY_LIGHT_DREAMING_CRON_EXPR = "0 */6 * * *"; export const DEFAULT_MEMORY_LIGHT_DREAMING_LOOKBACK_DAYS = 2;