mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-24 03:29:31 +00:00
fix(memory-core): report active dreaming phases in status (#93113)
* fix(memory-core): report active dreaming phases in status * fix(memory-core): repair active dreaming status phases --------- Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import path from "node:path";
|
||||
import type { MemoryEmbeddingProbeResult } from "openclaw/plugin-sdk/memory-core-host-engine-storage";
|
||||
import {
|
||||
resolveMemoryDreamingConfig,
|
||||
resolveMemoryLightDreamingConfig,
|
||||
resolveMemoryRemDreamingConfig,
|
||||
} from "openclaw/plugin-sdk/memory-core-host-status";
|
||||
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
||||
@@ -223,12 +224,23 @@ async function createHistoricalRemHarnessWorkspace(params: {
|
||||
|
||||
function formatDreamingSummary(cfg: OpenClawConfig): string {
|
||||
const pluginConfig = resolveMemoryPluginConfig(cfg);
|
||||
const dreaming = resolveShortTermPromotionDreamingConfig({ pluginConfig, cfg });
|
||||
if (!dreaming.enabled) {
|
||||
return "off";
|
||||
}
|
||||
const timezone = dreaming.timezone ? ` (${dreaming.timezone})` : "";
|
||||
return `${dreaming.cron}${timezone} · limit=${dreaming.limit} · minScore=${dreaming.minScore} · minRecallCount=${dreaming.minRecallCount} · minUniqueQueries=${dreaming.minUniqueQueries} · recencyHalfLifeDays=${dreaming.recencyHalfLifeDays} · maxAgeDays=${dreaming.maxAgeDays ?? "none"} · maxPromotedSnippetTokens=${dreaming.maxPromotedSnippetTokens}`;
|
||||
const light = resolveMemoryLightDreamingConfig({ pluginConfig, cfg });
|
||||
const deep = resolveShortTermPromotionDreamingConfig({ pluginConfig, cfg });
|
||||
const rem = resolveMemoryRemDreamingConfig({ pluginConfig, cfg });
|
||||
const timezone = deep.timezone ?? light.timezone ?? rem.timezone;
|
||||
const formatCron = (cron: string) => (timezone ? `${cron} (${timezone})` : cron);
|
||||
const lightSummary = light.enabled
|
||||
? `light=${formatCron(light.cron)} · limit=${light.limit} · lookbackDays=${light.lookbackDays}`
|
||||
: null;
|
||||
const remSummary = rem.enabled
|
||||
? `rem=${formatCron(rem.cron)} · limit=${rem.limit} · lookbackDays=${rem.lookbackDays} · minPatternStrength=${rem.minPatternStrength}`
|
||||
: null;
|
||||
const hasLighterPhase = light.enabled || rem.enabled;
|
||||
const deepLabel = hasLighterPhase ? "deep=" : "";
|
||||
const deepDetails = `${formatCron(deep.cron)} · limit=${deep.limit} · minScore=${deep.minScore} · minRecallCount=${deep.minRecallCount} · minUniqueQueries=${deep.minUniqueQueries} · recencyHalfLifeDays=${deep.recencyHalfLifeDays} · maxAgeDays=${deep.maxAgeDays ?? "none"} · maxPromotedSnippetTokens=${deep.maxPromotedSnippetTokens}`;
|
||||
const deepSummary = deep.enabled ? `${deepLabel}${deepDetails}` : null;
|
||||
const phases = [lightSummary, remSummary, deepSummary].filter(Boolean);
|
||||
return phases.length > 0 ? phases.join(" · ") : "off";
|
||||
}
|
||||
|
||||
function formatAuditCounts(audit: ShortTermAuditSummary): string {
|
||||
|
||||
@@ -746,6 +746,206 @@ describe("memory cli", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("reports light-only dreaming as active during status", async () => {
|
||||
getRuntimeConfig.mockReturnValue({
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-core": {
|
||||
config: {
|
||||
dreaming: {
|
||||
enabled: true,
|
||||
frequency: "5 * * * *",
|
||||
timezone: "UTC",
|
||||
phases: {
|
||||
light: {
|
||||
enabled: true,
|
||||
limit: 4,
|
||||
lookbackDays: 2,
|
||||
},
|
||||
deep: {
|
||||
enabled: false,
|
||||
},
|
||||
rem: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const close = vi.fn(async () => {});
|
||||
mockManager({
|
||||
probeVectorAvailability: vi.fn(async () => true),
|
||||
status: () => makeMemoryStatus(),
|
||||
close,
|
||||
});
|
||||
|
||||
const log = spyRuntimeLogs(defaultRuntime);
|
||||
await runMemoryCli(["status"]);
|
||||
|
||||
expectLogged(log, "Dreaming: light=5 * * * * (UTC) · limit=4 · lookbackDays=2");
|
||||
expect(close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports rem-only dreaming as active during status", async () => {
|
||||
getRuntimeConfig.mockReturnValue({
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-core": {
|
||||
config: {
|
||||
dreaming: {
|
||||
enabled: true,
|
||||
frequency: "0 6 * * 0",
|
||||
timezone: "UTC",
|
||||
phases: {
|
||||
light: {
|
||||
enabled: false,
|
||||
},
|
||||
deep: {
|
||||
enabled: false,
|
||||
},
|
||||
rem: {
|
||||
enabled: true,
|
||||
limit: 3,
|
||||
lookbackDays: 9,
|
||||
minPatternStrength: 0.81,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const close = vi.fn(async () => {});
|
||||
mockManager({
|
||||
probeVectorAvailability: vi.fn(async () => true),
|
||||
status: () => makeMemoryStatus(),
|
||||
close,
|
||||
});
|
||||
|
||||
const log = spyRuntimeLogs(defaultRuntime);
|
||||
await runMemoryCli(["status"]);
|
||||
|
||||
expectLogged(
|
||||
log,
|
||||
"Dreaming: rem=0 6 * * 0 (UTC) · limit=3 · lookbackDays=9 · minPatternStrength=0.81",
|
||||
);
|
||||
expect(close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("labels deep dreaming when multiple phases are active during status", async () => {
|
||||
getRuntimeConfig.mockReturnValue({
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-core": {
|
||||
config: {
|
||||
dreaming: {
|
||||
enabled: true,
|
||||
frequency: "15 2 * * *",
|
||||
timezone: "UTC",
|
||||
phases: {
|
||||
light: {
|
||||
enabled: true,
|
||||
limit: 5,
|
||||
lookbackDays: 1,
|
||||
},
|
||||
deep: {
|
||||
enabled: true,
|
||||
limit: 7,
|
||||
minScore: 0.72,
|
||||
minRecallCount: 4,
|
||||
minUniqueQueries: 2,
|
||||
recencyHalfLifeDays: 10,
|
||||
maxAgeDays: 45,
|
||||
maxPromotedSnippetTokens: 512,
|
||||
},
|
||||
rem: {
|
||||
enabled: true,
|
||||
limit: 2,
|
||||
lookbackDays: 14,
|
||||
minPatternStrength: 0.67,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const close = vi.fn(async () => {});
|
||||
mockManager({
|
||||
probeVectorAvailability: vi.fn(async () => true),
|
||||
status: () => makeMemoryStatus(),
|
||||
close,
|
||||
});
|
||||
|
||||
const log = spyRuntimeLogs(defaultRuntime);
|
||||
await runMemoryCli(["status"]);
|
||||
|
||||
expectLogged(log, "Dreaming: light=15 2 * * * (UTC) · limit=5 · lookbackDays=1");
|
||||
expectLogged(log, "rem=15 2 * * * (UTC) · limit=2 · lookbackDays=14 · minPatternStrength=0.67");
|
||||
expectLogged(log, "deep=15 2 * * * (UTC) · limit=7 · minScore=0.72");
|
||||
expectLogged(log, "minRecallCount=4");
|
||||
expectLogged(log, "maxPromotedSnippetTokens=512");
|
||||
expect(close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("preserves deep dreaming diagnostics during status", async () => {
|
||||
getRuntimeConfig.mockReturnValue({
|
||||
plugins: {
|
||||
entries: {
|
||||
"memory-core": {
|
||||
config: {
|
||||
dreaming: {
|
||||
enabled: true,
|
||||
frequency: "0 4 * * *",
|
||||
timezone: "UTC",
|
||||
phases: {
|
||||
light: {
|
||||
enabled: false,
|
||||
},
|
||||
deep: {
|
||||
enabled: true,
|
||||
limit: 6,
|
||||
minScore: 0.88,
|
||||
minRecallCount: 5,
|
||||
minUniqueQueries: 3,
|
||||
recencyHalfLifeDays: 12,
|
||||
maxAgeDays: 30,
|
||||
maxPromotedSnippetTokens: 640,
|
||||
},
|
||||
rem: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const close = vi.fn(async () => {});
|
||||
mockManager({
|
||||
probeVectorAvailability: vi.fn(async () => true),
|
||||
status: () => makeMemoryStatus(),
|
||||
close,
|
||||
});
|
||||
|
||||
const log = spyRuntimeLogs(defaultRuntime);
|
||||
await runMemoryCli(["status"]);
|
||||
|
||||
expectLogged(log, "Dreaming: 0 4 * * * (UTC) · limit=6 · minScore=0.88");
|
||||
expectLogged(log, "minRecallCount=5");
|
||||
expectLogged(log, "minUniqueQueries=3");
|
||||
expectLogged(log, "recencyHalfLifeDays=12");
|
||||
expectLogged(log, "maxAgeDays=30");
|
||||
expectLogged(log, "maxPromotedSnippetTokens=640");
|
||||
expect(close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("repairs invalid recall metadata and stale locks with status --fix", async () => {
|
||||
await withTempWorkspace(async (workspaceDir) => {
|
||||
await shortTermTesting.writeRawRecallStore(workspaceDir, {
|
||||
|
||||
Reference in New Issue
Block a user