Dreaming UI: use slot-aware configured state

This commit is contained in:
Vignesh Natarajan
2026-04-07 02:42:48 -07:00
committed by Vignesh
parent 9dda94c0f7
commit d84ac5b1eb
3 changed files with 100 additions and 20 deletions

View File

@@ -207,4 +207,39 @@ describe("memory dreaming host helpers", () => {
},
});
});
it('falls back to memory-core when memory slot is "none" or blank', () => {
expect(
resolveMemoryDreamingPluginId({
plugins: {
slots: {
memory: "none",
},
},
} as OpenClawConfig),
).toBe("memory-core");
expect(
resolveMemoryDreamingPluginConfig({
plugins: {
slots: {
memory: " ",
},
entries: {
"memory-core": {
config: {
dreaming: {
enabled: true,
},
},
},
},
},
} as OpenClawConfig),
).toEqual({
dreaming: {
enabled: true,
},
});
});
});

View File

@@ -68,6 +68,7 @@ import {
import {
loadDreamDiary,
loadDreamingStatus,
resolveConfiguredDreaming,
updateDreamingEnabled,
} from "./controllers/dreaming.ts";
import {
@@ -158,24 +159,6 @@ const lazySessions = createLazy(() => import("./views/sessions.ts"));
const lazySkills = createLazy(() => import("./views/skills.ts"));
const lazyDreamingView = createLazy(() => import("./views/dreaming.ts"));
function resolveConfiguredDreaming(configValue: Record<string, unknown> | null): {
enabled: boolean;
} {
if (!configValue) {
return {
enabled: false,
};
}
const plugins = configValue.plugins as Record<string, unknown> | undefined;
const entries = plugins?.entries as Record<string, unknown> | undefined;
const memoryCore = entries?.["memory-core"] as Record<string, unknown> | undefined;
const config = memoryCore?.config as Record<string, unknown> | undefined;
const dreaming = config?.dreaming as Record<string, unknown> | undefined;
return {
enabled: typeof dreaming?.enabled === "boolean" ? dreaming.enabled : false,
};
}
function formatDreamNextCycle(nextRunAtMs: number | undefined): string | null {
if (typeof nextRunAtMs !== "number" || !Number.isFinite(nextRunAtMs)) {
return null;

View File

@@ -29,6 +29,13 @@ function createState(): { state: DreamingState; request: ReturnType<typeof vi.fn
return { state, request };
}
function getConfigPatchRawPayload(request: ReturnType<typeof vi.fn>): Record<string, unknown> {
const patchCall = request.mock.calls.find((entry) => entry[0] === "config.patch");
expect(patchCall).toBeDefined();
const requestPayload = patchCall?.[1] as { raw?: string };
return JSON.parse(String(requestPayload.raw)) as Record<string, unknown>;
}
describe("dreaming controller", () => {
it("loads and normalizes dreaming status from doctor.memory.status", async () => {
const { state, request } = createState();
@@ -137,8 +144,7 @@ describe("dreaming controller", () => {
sessionKey: "main",
}),
);
const requestPayload = request.mock.calls[0]?.[1] as { raw?: string };
expect(JSON.parse(String(requestPayload.raw))).toEqual({
expect(getConfigPatchRawPayload(request)).toEqual({
plugins: {
entries: {
"memos-local-openclaw-plugin": {
@@ -155,6 +161,38 @@ describe("dreaming controller", () => {
expect(state.dreamingStatusError).toBeNull();
});
it("falls back to memory-core when selected memory slot is blank", async () => {
const { state, request } = createState();
state.configSnapshot = {
hash: "hash-1",
config: {
plugins: {
slots: {
memory: " ",
},
},
},
};
request.mockResolvedValue({ ok: true });
const ok = await updateDreamingEnabled(state, true);
expect(ok).toBe(true);
expect(getConfigPatchRawPayload(request)).toEqual({
plugins: {
entries: {
"memory-core": {
config: {
dreaming: {
enabled: true,
},
},
},
},
},
});
});
it("reads dreaming enabled state from the selected memory slot plugin", () => {
expect(
resolveConfiguredDreaming({
@@ -186,6 +224,30 @@ describe("dreaming controller", () => {
});
});
it('falls back to memory-core when selected memory slot is "none"', () => {
expect(
resolveConfiguredDreaming({
plugins: {
slots: {
memory: "none",
},
entries: {
"memory-core": {
config: {
dreaming: {
enabled: true,
},
},
},
},
},
}),
).toEqual({
pluginId: "memory-core",
enabled: true,
});
});
it("fails gracefully when config hash is missing", async () => {
const { state, request } = createState();
state.configSnapshot = {};