

























@@ -5,7 +5,7 @@ import {
55enqueueSystemEvent,
66resetSystemEventsForTest,
77} from "openclaw/plugin-sdk/system-event-runtime";
8-import { afterEach, describe, expect, it, vi } from "vitest";
8+import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
99import {
1010testing,
1111reconcileShortTermDreamingCronJob,
@@ -838,6 +838,95 @@ describe("short-term dreaming cron reconciliation", () => {
838838});
839839840840describe("gateway startup reconciliation", () => {
841+let liveConfigRunPayloadCase: {
842+result: unknown;
843+runtimeConfigCalled: boolean;
844+warnCalls: unknown[][];
845+};
846+847+beforeAll(async () => {
848+clearInternalHooks();
849+const logger = createLogger();
850+const harness = createCronHarness();
851+const onMock = vi.fn();
852+const workspaceDir = await createTempWorkspace("memory-dreaming-live-config-workspace-");
853+const runtimeCurrentConfig = vi.fn(
854+() =>
855+({
856+agents: {
857+list: [{ id: "main", default: true, workspace: workspaceDir }],
858+},
859+plugins: {
860+entries: {
861+"memory-core": {
862+config: {
863+dreaming: {
864+enabled: true,
865+frequency: "15 4 * * *",
866+timezone: "UTC",
867+limit: 0,
868+},
869+},
870+},
871+},
872+},
873+}) as OpenClawConfig,
874+);
875+const api: DreamingPluginApiTestDouble = {
876+config: {
877+plugins: {
878+entries: {
879+"memory-core": {
880+config: {
881+dreaming: {
882+enabled: true,
883+frequency: "15 4 * * *",
884+timezone: "UTC",
885+limit: 5,
886+},
887+},
888+},
889+},
890+},
891+} as OpenClawConfig,
892+pluginConfig: {},
893+ logger,
894+runtime: {
895+config: {
896+current: runtimeCurrentConfig,
897+},
898+},
899+on: onMock,
900+};
901+902+try {
903+registerShortTermPromotionDreamingForTest(api);
904+await triggerGatewayStart(onMock, {
905+config: api.config,
906+getCron: () => harness.cron,
907+});
908+909+const sessionKey = "agent:main:main";
910+enqueueSystemEvent(constants.DREAMING_SYSTEM_EVENT_TEXT, {
911+ sessionKey,
912+contextKey: "cron:memory-dreaming",
913+});
914+915+const beforeAgentReply = getBeforeAgentReplyHandler(onMock);
916+liveConfigRunPayloadCase = {
917+result: await beforeAgentReply(
918+{ cleanedBody: constants.DREAMING_SYSTEM_EVENT_TEXT },
919+{ trigger: "heartbeat", sessionKey },
920+),
921+runtimeConfigCalled: runtimeCurrentConfig.mock.calls.length > 0,
922+warnCalls: [...logger.warn.mock.calls],
923+};
924+} finally {
925+await triggerGatewayStop(onMock).catch(() => undefined);
926+clearInternalHooks();
927+}
928+});
929+841930it("uses the startup cfg when reconciling the managed dreaming cron job", async () => {
842931clearInternalHooks();
843932const logger = createLogger();
@@ -1497,6 +1586,7 @@ describe("gateway startup reconciliation", () => {
1497158614981587expectLogContains(logger.warn, "cron service unavailable");
14991588} finally {
1589+await triggerGatewayStop(onMock);
15001590clearInternalHooks();
15011591}
15021592});
@@ -1540,12 +1630,13 @@ describe("gateway startup reconciliation", () => {
15401630// (e.g. the cron service genuinely failed to initialize). The warning must fire.
15411631const beforeAgentReply = getBeforeAgentReplyHandler(onMock);
15421632await beforeAgentReply(
1543-{ cleanedBody: constants.DREAMING_SYSTEM_EVENT_TEXT },
1633+{ cleanedBody: "" },
15441634{ trigger: "cron", workspaceDir: ".", sessionKey: "agent:main:cron:job-managed" },
15451635);
1546163615471637expectLogContains(logger.warn, "cron service unavailable");
15481638} finally {
1639+await triggerGatewayStop(onMock);
15491640clearInternalHooks();
15501641}
15511642});
@@ -1864,90 +1955,14 @@ describe("gateway startup reconciliation", () => {
18641955});
1865195618661957it("uses live runtime config for the heartbeat dreaming run payload", async () => {
1867-clearInternalHooks();
1868-const logger = createLogger();
1869-const harness = createCronHarness();
1870-const onMock = vi.fn();
1871-const workspaceDir = await createTempWorkspace("memory-dreaming-live-config-workspace-");
1872-const runtimeCurrentConfig = vi.fn(
1873-() =>
1874-({
1875-agents: {
1876-list: [{ id: "main", default: true, workspace: workspaceDir }],
1877-},
1878-plugins: {
1879-entries: {
1880-"memory-core": {
1881-config: {
1882-dreaming: {
1883-enabled: true,
1884-frequency: "15 4 * * *",
1885-timezone: "UTC",
1886-limit: 0,
1887-},
1888-},
1889-},
1890-},
1891-},
1892-}) as OpenClawConfig,
1893-);
1894-const api: DreamingPluginApiTestDouble = {
1895-config: {
1896-plugins: {
1897-entries: {
1898-"memory-core": {
1899-config: {
1900-dreaming: {
1901-enabled: true,
1902-frequency: "15 4 * * *",
1903-timezone: "UTC",
1904-limit: 5,
1905-},
1906-},
1907-},
1908-},
1909-},
1910-} as OpenClawConfig,
1911-pluginConfig: {},
1912- logger,
1913-runtime: {
1914-config: {
1915-current: runtimeCurrentConfig,
1916-},
1917-},
1918-on: onMock,
1919-};
1920-1921-try {
1922-registerShortTermPromotionDreamingForTest(api);
1923-await triggerGatewayStart(onMock, {
1924-config: api.config,
1925-getCron: () => harness.cron,
1926-});
1927-1928-const sessionKey = "agent:main:main";
1929-enqueueSystemEvent(constants.DREAMING_SYSTEM_EVENT_TEXT, {
1930- sessionKey,
1931-contextKey: "cron:memory-dreaming",
1932-});
1933-1934-const beforeAgentReply = getBeforeAgentReplyHandler(onMock);
1935-const result = await beforeAgentReply(
1936-{ cleanedBody: constants.DREAMING_SYSTEM_EVENT_TEXT },
1937-{ trigger: "heartbeat", sessionKey },
1938-);
1939-1940-expect(result).toEqual({
1941-handled: true,
1942-reason: "memory-core: short-term dreaming processed",
1943-});
1944-expect(runtimeCurrentConfig).toHaveBeenCalled();
1945-expect(logger.warn).not.toHaveBeenCalledWith(
1946-"memory-core: dreaming promotion skipped because no memory workspace is available.",
1947-);
1948-} finally {
1949-clearInternalHooks();
1950-}
1958+expect(liveConfigRunPayloadCase.result).toEqual({
1959+handled: true,
1960+reason: "memory-core: short-term dreaming processed",
1961+});
1962+expect(liveConfigRunPayloadCase.runtimeConfigCalled).toBe(true);
1963+expect(liveConfigRunPayloadCase.warnCalls).not.toContainEqual([
1964+"memory-core: dreaming promotion skipped because no memory workspace is available.",
1965+]);
19511966});
1952196719531968it("does not fall back to startup plugin config when live memory-core config is removed", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。