diff --git a/extensions/memory-lancedb/config.test.ts b/extensions/memory-lancedb/config.test.ts new file mode 100644 index 00000000000..dc7479d312f --- /dev/null +++ b/extensions/memory-lancedb/config.test.ts @@ -0,0 +1,53 @@ +import fs from "node:fs"; +import { describe, expect, it } from "vitest"; +import { validateJsonSchemaValue } from "../../src/plugins/schema-validator.js"; +import { memoryConfigSchema } from "./config.js"; + +const manifest = JSON.parse( + fs.readFileSync(new URL("./openclaw.plugin.json", import.meta.url), "utf-8"), +) as { configSchema: Record }; + +describe("memory-lancedb config", () => { + it("accepts dreaming in the manifest schema and preserves it in runtime parsing", () => { + const manifestResult = validateJsonSchemaValue({ + schema: manifest.configSchema, + cacheKey: "memory-lancedb.manifest.dreaming", + value: { + embedding: { + apiKey: "sk-test", + }, + dreaming: { + enabled: true, + }, + }, + }); + + const parsed = memoryConfigSchema.parse({ + embedding: { + apiKey: "sk-test", + }, + dreaming: { + enabled: true, + }, + }); + + expect(manifestResult.ok).toBe(true); + expect(parsed.dreaming).toEqual({ + enabled: true, + }); + }); + + it("still rejects unrelated unknown top-level config keys", () => { + expect(() => { + memoryConfigSchema.parse({ + embedding: { + apiKey: "sk-test", + }, + dreaming: { + enabled: true, + }, + unexpected: true, + }); + }).toThrow("memory config has unknown keys: unexpected"); + }); +}); diff --git a/extensions/memory-lancedb/config.ts b/extensions/memory-lancedb/config.ts index 9b71e3992d0..316e5e0ce67 100644 --- a/extensions/memory-lancedb/config.ts +++ b/extensions/memory-lancedb/config.ts @@ -10,6 +10,7 @@ export type MemoryConfig = { baseUrl?: string; dimensions?: number; }; + dreaming?: unknown; dbPath?: string; autoCapture?: boolean; autoRecall?: boolean; @@ -97,7 +98,7 @@ export const memoryConfigSchema = { const cfg = value as Record; assertAllowedKeys( cfg, - ["embedding", "dbPath", "autoCapture", "autoRecall", "captureMaxChars"], + ["embedding", "dreaming", "dbPath", "autoCapture", "autoRecall", "captureMaxChars"], "memory config", ); @@ -127,6 +128,7 @@ export const memoryConfigSchema = { typeof embedding.baseUrl === "string" ? resolveEnvVars(embedding.baseUrl) : undefined, dimensions: typeof embedding.dimensions === "number" ? embedding.dimensions : undefined, }, + dreaming: cfg.dreaming, dbPath: typeof cfg.dbPath === "string" ? cfg.dbPath : DEFAULT_DB_PATH, autoCapture: cfg.autoCapture === true, autoRecall: cfg.autoRecall !== false, diff --git a/extensions/memory-lancedb/openclaw.plugin.json b/extensions/memory-lancedb/openclaw.plugin.json index 754407380b5..b19e3f3a50f 100644 --- a/extensions/memory-lancedb/openclaw.plugin.json +++ b/extensions/memory-lancedb/openclaw.plugin.json @@ -38,6 +38,10 @@ "label": "Auto-Recall", "help": "Automatically inject relevant memories into context" }, + "dreaming": { + "label": "Dreaming", + "help": "Optional dreaming config consumed when this plugin owns the memory slot" + }, "captureMaxChars": { "label": "Capture Max Chars", "help": "Maximum message length eligible for auto-capture", @@ -77,6 +81,9 @@ "autoRecall": { "type": "boolean" }, + "dreaming": { + "type": "object" + }, "captureMaxChars": { "type": "number", "minimum": 100, diff --git a/src/memory-host-sdk/dreaming.test.ts b/src/memory-host-sdk/dreaming.test.ts index b5f2c9cbb3d..687f34e170d 100644 --- a/src/memory-host-sdk/dreaming.test.ts +++ b/src/memory-host-sdk/dreaming.test.ts @@ -187,6 +187,30 @@ describe("memory dreaming host helpers", () => { enabled: true, }, }); + expect( + resolveMemoryDreamingPluginConfig({ + plugins: { + slots: { + memory: "memory-lancedb", + }, + entries: { + "memory-lancedb": { + config: { + dreaming: { + enabled: true, + frequency: "0 */6 * * *", + }, + }, + }, + }, + }, + } as OpenClawConfig), + ).toEqual({ + dreaming: { + enabled: true, + frequency: "0 */6 * * *", + }, + }); expect( resolveMemoryDreamingPluginConfig({ plugins: {