diff --git a/extensions/memory-lancedb/config.ts b/extensions/memory-lancedb/config.ts
index 4caa48cdce..339e5c8cd7 100644
--- a/extensions/memory-lancedb/config.ts
+++ b/extensions/memory-lancedb/config.ts
@@ -18,7 +18,7 @@ export const MEMORY_CATEGORIES = ["preference", "fact", "decision", "entity", "o
export type MemoryCategory = (typeof MEMORY_CATEGORIES)[number];
const DEFAULT_MODEL = "text-embedding-3-small";
-const DEFAULT_CAPTURE_MAX_CHARS = 1500;
+export const DEFAULT_CAPTURE_MAX_CHARS = 500;
const LEGACY_STATE_DIRS: string[] = [];
function resolveDefaultDbPath(): string {
diff --git a/extensions/memory-lancedb/index.test.ts b/extensions/memory-lancedb/index.test.ts
index b5261f848a..c2cb431e78 100644
--- a/extensions/memory-lancedb/index.test.ts
+++ b/extensions/memory-lancedb/index.test.ts
@@ -61,7 +61,7 @@ describe("memory plugin e2e", () => {
expect(config).toBeDefined();
expect(config?.embedding?.apiKey).toBe(OPENAI_API_KEY);
expect(config?.dbPath).toBe(dbPath);
- expect(config?.captureMaxChars).toBe(1500);
+ expect(config?.captureMaxChars).toBe(500);
});
test("config schema resolves env vars", async () => {
@@ -105,6 +105,21 @@ describe("memory plugin e2e", () => {
}).toThrow("captureMaxChars must be between 100 and 10000");
});
+ test("config schema accepts captureMaxChars override", async () => {
+ const { default: memoryPlugin } = await import("./index.js");
+
+ const config = memoryPlugin.configSchema?.parse?.({
+ embedding: {
+ apiKey: OPENAI_API_KEY,
+ model: "text-embedding-3-small",
+ },
+ dbPath,
+ captureMaxChars: 1800,
+ });
+
+ expect(config?.captureMaxChars).toBe(1800);
+ });
+
test("shouldCapture applies real capture rules", async () => {
const { shouldCapture } = await import("./index.js");
@@ -117,10 +132,14 @@ describe("memory plugin e2e", () => {
expect(shouldCapture("injected")).toBe(false);
expect(shouldCapture("status")).toBe(false);
expect(shouldCapture("Here is a short **summary**\n- bullet")).toBe(false);
- const longButAllowed = `I always prefer this style. ${"x".repeat(1200)}`;
- const tooLong = `I always prefer this style. ${"x".repeat(1600)}`;
- expect(shouldCapture(longButAllowed, { maxChars: 1500 })).toBe(true);
- expect(shouldCapture(tooLong, { maxChars: 1500 })).toBe(false);
+ const defaultAllowed = `I always prefer this style. ${"x".repeat(400)}`;
+ const defaultTooLong = `I always prefer this style. ${"x".repeat(600)}`;
+ expect(shouldCapture(defaultAllowed)).toBe(true);
+ expect(shouldCapture(defaultTooLong)).toBe(false);
+ const customAllowed = `I always prefer this style. ${"x".repeat(1200)}`;
+ const customTooLong = `I always prefer this style. ${"x".repeat(1600)}`;
+ expect(shouldCapture(customAllowed, { maxChars: 1500 })).toBe(true);
+ expect(shouldCapture(customTooLong, { maxChars: 1500 })).toBe(false);
});
test("detectCategory classifies using production logic", async () => {
diff --git a/extensions/memory-lancedb/index.ts b/extensions/memory-lancedb/index.ts
index aa53d834dd..0778006c7b 100644
--- a/extensions/memory-lancedb/index.ts
+++ b/extensions/memory-lancedb/index.ts
@@ -12,6 +12,7 @@ import { Type } from "@sinclair/typebox";
import { randomUUID } from "node:crypto";
import OpenAI from "openai";
import {
+ DEFAULT_CAPTURE_MAX_CHARS,
MEMORY_CATEGORIES,
type MemoryCategory,
memoryConfigSchema,
@@ -195,7 +196,7 @@ const MEMORY_TRIGGERS = [
];
export function shouldCapture(text: string, options?: { maxChars?: number }): boolean {
- const maxChars = options?.maxChars ?? 1500;
+ const maxChars = options?.maxChars ?? DEFAULT_CAPTURE_MAX_CHARS;
if (text.length < 10 || text.length > maxChars) {
return false;
}
diff --git a/extensions/memory-lancedb/openclaw.plugin.json b/extensions/memory-lancedb/openclaw.plugin.json
index 007ea3d63d..44ee0dcd04 100644
--- a/extensions/memory-lancedb/openclaw.plugin.json
+++ b/extensions/memory-lancedb/openclaw.plugin.json
@@ -30,7 +30,7 @@
"label": "Capture Max Chars",
"help": "Maximum message length eligible for auto-capture",
"advanced": true,
- "placeholder": "1500"
+ "placeholder": "500"
}
},
"configSchema": {