diff --git a/hindsight-integrations/openclaw/README.md b/hindsight-integrations/openclaw/README.md index f2d573789..b17900dbd 100644 --- a/hindsight-integrations/openclaw/README.md +++ b/hindsight-integrations/openclaw/README.md @@ -102,6 +102,7 @@ Optional settings in `~/.openclaw/openclaw.json` under `plugins.entries.hindsigh | `retainRoles` | `["user", "assistant"]` | Which message roles to retain. Options: `user`, `assistant`, `system`, `tool` | | `retainFormat` | `"json"` | Serialization format for retained conversation content. `"json"` emits a structured array of `{role, content}` messages (matches Claude Code). `"text"` emits legacy `[role: x] … [x:end]` markers. | | `retainToolCalls` | `true` | With `retainFormat: "json"`, each message's content is an Anthropic-shaped block array (`text` / `tool_use` / `tool_result`). Tool results are truncated at 2000 chars. Hindsight's own MCP tools (recall/retain/search/…) are filtered to prevent feedback loops. Set `false` to retain text-only content. | +| `retainDocumentScope` | `"session"` | Granularity of retained document IDs. `"session"` appends turns to one document per OpenClaw session when the Hindsight API supports append. `"turn"` creates a separate document per retain (`...:turn:000001` / `...:window:000002`). | | `retainEveryNTurns` | `1` | Retain every Nth turn. `1` = every turn (default). Values > 1 enable chunked retention with a sliding window. | | `retainOverlapTurns` | `0` | Extra prior turns included when chunked retention fires. Window = `retainEveryNTurns + retainOverlapTurns`. Only applies when `retainEveryNTurns > 1`. | | `recallBudget` | `"mid"` | Recall effort: `low`, `mid`, or `high`. Higher budgets use more retrieval strategies. | diff --git a/hindsight-integrations/openclaw/src/index.test.ts b/hindsight-integrations/openclaw/src/index.test.ts index 78d255a50..e79a28b38 100644 --- a/hindsight-integrations/openclaw/src/index.test.ts +++ b/hindsight-integrations/openclaw/src/index.test.ts @@ -1356,6 +1356,24 @@ function makeApi(rawConfig: Record): MoltbotPluginAPI { } as unknown as MoltbotPluginAPI; } +describe("getPluginConfig — retainDocumentScope whitelist", () => { + it("passes retainDocumentScope='turn' through when set", () => { + const cfg = getPluginConfig(makeApi({ retainDocumentScope: "turn" })); + + expect(cfg.retainDocumentScope).toBe("turn"); + }); + + it("defaults retainDocumentScope to session for missing or invalid values", () => { + expect(getPluginConfig(makeApi({})).retainDocumentScope).toBe("session"); + expect(getPluginConfig(makeApi({ retainDocumentScope: "session" })).retainDocumentScope).toBe( + "session" + ); + expect(getPluginConfig(makeApi({ retainDocumentScope: "window" })).retainDocumentScope).toBe( + "session" + ); + }); +}); + describe("getPluginConfig — retainQueue whitelist (#1443)", () => { it("passes retainQueuePath through when set to a non-empty string", () => { const cfg = getPluginConfig(makeApi({ retainQueuePath: "/custom/path/retain.jsonl" })); diff --git a/hindsight-integrations/openclaw/src/index.ts b/hindsight-integrations/openclaw/src/index.ts index d46fa15ee..416aad07c 100644 --- a/hindsight-integrations/openclaw/src/index.ts +++ b/hindsight-integrations/openclaw/src/index.ts @@ -1480,6 +1480,7 @@ export function getPluginConfig(api: MoltbotPluginAPI): PluginConfig { retainRoles: Array.isArray(config.retainRoles) ? config.retainRoles : undefined, retainFormat: config.retainFormat === "text" ? "text" : "json", retainToolCalls: config.retainToolCalls !== false, + retainDocumentScope: config.retainDocumentScope === "turn" ? "turn" : "session", recallBudget: config.recallBudget || "mid", recallMaxTokens: config.recallMaxTokens || 1024, recallTypes: Array.isArray(config.recallTypes) ? config.recallTypes : ["observation"],