fix(memory-lancedb): accept dreaming config for slot-owned memory (#63874)

Merged via squash.

Prepared head SHA: 9aaf29bd36
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Co-authored-by: mbelinky <132747814+mbelinky@users.noreply.github.com>
Reviewed-by: @mbelinky
This commit is contained in:
Mariano
2026-04-09 23:03:53 +02:00
committed by GitHub
parent 820dc38525
commit 4bd720527b
5 changed files with 120 additions and 1 deletions

View File

@@ -49,6 +49,7 @@ Docs: https://docs.openclaw.ai
- Matrix/runtime: resolve the verification/bootstrap runtime from a distinct packaged Matrix entry so global npm installs stop failing on crypto bootstrap with missing-module or recursive runtime alias errors. (#59249) Thanks @gumadeiras.
- Matrix/streaming: preserve ordered block flushes before tool, message, and agent boundaries, add explicit `channels.matrix.blockStreaming` opt-in so Matrix `streaming: "off"` stays final-only by default, and move MiniMax plain-text final handling into the MiniMax provider runtime instead of the shared core heuristic. (#59266) thanks @gumadeiras
- Gateway/agents: fix stale run-context TTL cleanup so the new maintenance sweep compiles and resets orphaned run sequence state correctly. (#52731) thanks @artwalker
- Memory/lancedb: accept `dreaming` config when `memory-lancedb` owns the memory slot so Dreaming surfaces can read slot-owner settings without schema rejection. (#63874) Thanks @mbelinky.
## 2026.4.9

View File

@@ -0,0 +1,64 @@
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<string, unknown> };
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");
});
it("rejects non-object dreaming values in runtime parsing", () => {
expect(() => {
memoryConfigSchema.parse({
embedding: {
apiKey: "sk-test",
},
dreaming: true,
});
}).toThrow("dreaming config must be an object");
});
});

View File

@@ -10,6 +10,7 @@ export type MemoryConfig = {
baseUrl?: string;
dimensions?: number;
};
dreaming?: Record<string, unknown>;
dbPath?: string;
autoCapture?: boolean;
autoRecall?: boolean;
@@ -97,7 +98,7 @@ export const memoryConfigSchema = {
const cfg = value as Record<string, unknown>;
assertAllowedKeys(
cfg,
["embedding", "dbPath", "autoCapture", "autoRecall", "captureMaxChars"],
["embedding", "dreaming", "dbPath", "autoCapture", "autoRecall", "captureMaxChars"],
"memory config",
);
@@ -118,6 +119,15 @@ export const memoryConfigSchema = {
throw new Error("captureMaxChars must be between 100 and 10000");
}
const dreaming =
typeof cfg.dreaming === "undefined"
? undefined
: cfg.dreaming && typeof cfg.dreaming === "object" && !Array.isArray(cfg.dreaming)
? (cfg.dreaming as Record<string, unknown>)
: (() => {
throw new Error("dreaming config must be an object");
})();
return {
embedding: {
provider: "openai",
@@ -127,6 +137,7 @@ export const memoryConfigSchema = {
typeof embedding.baseUrl === "string" ? resolveEnvVars(embedding.baseUrl) : undefined,
dimensions: typeof embedding.dimensions === "number" ? embedding.dimensions : undefined,
},
dreaming,
dbPath: typeof cfg.dbPath === "string" ? cfg.dbPath : DEFAULT_DB_PATH,
autoCapture: cfg.autoCapture === true,
autoRecall: cfg.autoRecall !== false,

View File

@@ -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,

View File

@@ -156,6 +156,9 @@ describe("memory dreaming host helpers", () => {
"America/Los_Angeles",
),
).toBe(true);
});
it("resolves the configured memory-slot plugin id", () => {
expect(
resolveMemoryDreamingPluginId({
plugins: {
@@ -165,6 +168,9 @@ describe("memory dreaming host helpers", () => {
},
} as OpenClawConfig),
).toBe("memos-local-openclaw-plugin");
});
it("reads dreaming config from the configured memory-slot owner", () => {
expect(
resolveMemoryDreamingPluginConfig({
plugins: {
@@ -187,6 +193,36 @@ describe("memory dreaming host helpers", () => {
enabled: true,
},
});
});
it("reads dreaming config from memory-lancedb when it owns the memory slot", () => {
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 * * *",
},
});
});
it("falls back to memory-core when no memory slot override is configured", () => {
expect(
resolveMemoryDreamingPluginConfig({
plugins: {