


















11// Memory Core tests cover dreaming command plugin behavior.
22import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
3-import type {
4-OpenClawPluginCommandDefinition,
5-PluginCommandContext,
6-} from "openclaw/plugin-sdk/core";
3+import type { PluginCommandContext } from "openclaw/plugin-sdk/core";
74import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
85import { describe, expect, it, vi } from "vitest";
9-import { registerDreamingCommand } from "./dreaming-command.js";
6+import { handleDreamingCommand } from "./dreaming-command.js";
107118function asRecord(value: unknown): Record<string, unknown> | null {
129if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -22,7 +19,6 @@ function resolveStoredDreaming(config: OpenClawConfig): Record<string, unknown>
2219}
23202421function createHarness(initialConfig: OpenClawConfig = {}) {
25-const registered: { command?: OpenClawPluginCommandDefinition } = {};
2622let runtimeConfig: OpenClawConfig = initialConfig;
27232824const runtime = {
@@ -55,19 +51,10 @@ function createHarness(initialConfig: OpenClawConfig = {}) {
55515652const api = {
5753 runtime,
58-registerCommand: vi.fn((definition: OpenClawPluginCommandDefinition) => {
59-registered.command = definition;
60-}),
6154} as unknown as OpenClawPluginApi;
625563-registerDreamingCommand(api);
64-65-if (!registered.command) {
66-throw new Error("memory-core did not register /dreaming");
67-}
68-6956return {
70-command: registered.command,
57+api,
7158 runtime,
7259getRuntimeConfig: () => runtimeConfig,
7360};
@@ -90,17 +77,18 @@ function createCommandContext(
9077};
9178}
927993-describe("memory-core /dreaming command", () => {
94-it("registers with an enable/disable description", () => {
95- const { command } = createHarness();
96- expect(command.name).toBe("dreaming");
97- expect(command.acceptsArgs).toBe(true);
98- expect(command.description).toContain("Enable or disable");
99- });
80+async function runDreamingCommand(
81+harness: ReturnType<typeof createHarness>,
82+args?: string,
83+overrides?: Partial<Pick<PluginCommandContext, "gatewayClientScopes">>,
84+) {
85+return await handleDreamingCommand(harness.api, createCommandContext(args, overrides));
86+}
1008788+describe("memory-core /dreaming command", () => {
10189it("shows phase explanations when invoked without args", async () => {
102-const { command } = createHarness();
103-const result = await command.handler(createCommandContext());
90+const harness = createHarness();
91+const result = await runDreamingCommand(harness);
1049210593expect(result.text).toContain("Usage: /dreaming status");
10694expect(result.text).toContain("Dreaming status:");
@@ -111,7 +99,7 @@ describe("memory-core /dreaming command", () => {
11199});
112100113101it("persists global enablement under plugins.entries.memory-core.config.dreaming.enabled", async () => {
114-const { command, runtime, getRuntimeConfig } = createHarness({
102+const harness = createHarness({
115103plugins: {
116104entries: {
117105"memory-core": {
@@ -130,57 +118,51 @@ describe("memory-core /dreaming command", () => {
130118},
131119});
132120133-const result = await command.handler(createCommandContext("off"));
121+const result = await runDreamingCommand(harness, "off");
134122135-expect(runtime.config.mutateConfigFile).toHaveBeenCalledTimes(1);
136-const storedDreaming = resolveStoredDreaming(getRuntimeConfig());
123+expect(harness.runtime.config.mutateConfigFile).toHaveBeenCalledTimes(1);
124+const storedDreaming = resolveStoredDreaming(harness.getRuntimeConfig());
137125expect(storedDreaming.enabled).toBe(false);
138126expect(storedDreaming.frequency).toBe("0 */6 * * *");
139127expect(result.text).toContain("Dreaming disabled.");
140128});
141129142130it("blocks unscoped gateway callers from persisting dreaming config", async () => {
143-const { command, runtime } = createHarness();
131+const harness = createHarness();
144132145-const result = await command.handler(
146-createCommandContext("off", {
147-gatewayClientScopes: [],
148-}),
149-);
133+const result = await runDreamingCommand(harness, "off", {
134+gatewayClientScopes: [],
135+});
150136151137expect(result.text).toContain("requires operator.admin");
152-expect(runtime.config.mutateConfigFile).not.toHaveBeenCalled();
138+expect(harness.runtime.config.mutateConfigFile).not.toHaveBeenCalled();
153139});
154140155141it("blocks write-scoped gateway callers from persisting dreaming config", async () => {
156-const { command, runtime } = createHarness();
142+const harness = createHarness();
157143158-const result = await command.handler(
159-createCommandContext("off", {
160-gatewayClientScopes: ["operator.write"],
161-}),
162-);
144+const result = await runDreamingCommand(harness, "off", {
145+gatewayClientScopes: ["operator.write"],
146+});
163147164148expect(result.text).toContain("requires operator.admin");
165-expect(runtime.config.mutateConfigFile).not.toHaveBeenCalled();
149+expect(harness.runtime.config.mutateConfigFile).not.toHaveBeenCalled();
166150});
167151168152it("allows admin-scoped gateway callers to persist dreaming config", async () => {
169-const { command, runtime, getRuntimeConfig } = createHarness();
153+const harness = createHarness();
170154171-const result = await command.handler(
172-createCommandContext("on", {
173-gatewayClientScopes: ["operator.admin"],
174-}),
175-);
155+const result = await runDreamingCommand(harness, "on", {
156+gatewayClientScopes: ["operator.admin"],
157+});
176158177-expect(runtime.config.mutateConfigFile).toHaveBeenCalledTimes(1);
178-expect(resolveStoredDreaming(getRuntimeConfig()).enabled).toBe(true);
159+expect(harness.runtime.config.mutateConfigFile).toHaveBeenCalledTimes(1);
160+expect(resolveStoredDreaming(harness.getRuntimeConfig()).enabled).toBe(true);
179161expect(result.text).toContain("Dreaming enabled.");
180162});
181163182164it("returns status without mutating config", async () => {
183-const { command, runtime } = createHarness({
165+const harness = createHarness({
184166plugins: {
185167entries: {
186168"memory-core": {
@@ -199,20 +181,20 @@ describe("memory-core /dreaming command", () => {
199181},
200182});
201183202-const result = await command.handler(createCommandContext("status"));
184+const result = await runDreamingCommand(harness, "status");
203185204186expect(result.text).toContain("Dreaming status:");
205187expect(result.text).toContain("- enabled: off (America/Los_Angeles)");
206188expect(result.text).toContain("- sweep cadence: 15 */8 * * *");
207189expect(result.text).toContain("- promotion policy: score>=0.8, recalls>=3, uniqueQueries>=3");
208-expect(runtime.config.mutateConfigFile).not.toHaveBeenCalled();
190+expect(harness.runtime.config.mutateConfigFile).not.toHaveBeenCalled();
209191});
210192211193it("shows usage for invalid args and does not mutate config", async () => {
212-const { command, runtime } = createHarness();
213-const result = await command.handler(createCommandContext("unknown-mode"));
194+const harness = createHarness();
195+const result = await runDreamingCommand(harness, "unknown-mode");
214196215197expect(result.text).toContain("Usage: /dreaming status");
216-expect(runtime.config.mutateConfigFile).not.toHaveBeenCalled();
198+expect(harness.runtime.config.mutateConfigFile).not.toHaveBeenCalled();
217199});
218200});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。