@contextableai/openclaw-memory-rebac 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -1
- package/dist/cli.js +3 -3
- package/dist/config.d.ts +4 -0
- package/dist/config.js +17 -1
- package/dist/index.js +27 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -163,6 +163,25 @@ When enabled (default: `true`), the plugin captures the last N messages from eac
|
|
|
163
163
|
- Skips messages shorter than 5 characters and injected context blocks
|
|
164
164
|
- Uses custom extraction instructions for entity/fact extraction
|
|
165
165
|
|
|
166
|
+
### Session Filtering
|
|
167
|
+
|
|
168
|
+
Both auto-recall and auto-capture can be filtered by session key pattern using the `sessionFilter` config option. This is useful for excluding cron jobs, monitoring sessions, or other automated processes that generate repetitive, low-value data.
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"sessionFilter": {
|
|
173
|
+
"excludePatterns": ["cron", "monitoring", "healthcheck"]
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- **`excludePatterns`**: Array of strings. If the session key contains any of these substrings, auto-recall and auto-capture are skipped for that session.
|
|
179
|
+
- **`includePatterns`**: Array of strings. If set, only sessions whose key contains at least one of these substrings will trigger auto-recall/capture.
|
|
180
|
+
- If both are set, `excludePatterns` takes priority (exclude first, then check include).
|
|
181
|
+
- If neither is set, all sessions are captured (default behavior).
|
|
182
|
+
|
|
183
|
+
Filtered sessions still have full access to explicit memory tools (`memory_recall`, `memory_store`, `memory_forget`, `memory_status`). This means a cron job that consolidates memories can still use `memory_recall` and `memory_store` directly — only the automatic hooks are suppressed.
|
|
184
|
+
|
|
166
185
|
## Authorization Model
|
|
167
186
|
|
|
168
187
|
The SpiceDB schema defines four object types:
|
|
@@ -270,6 +289,8 @@ Agents without an `identities` entry (like service agents) are not linked to any
|
|
|
270
289
|
| `identities` | object | `{}` | Maps agent IDs to owner person IDs for cross-agent recall (see [Identity Linking](#identity-linking)) |
|
|
271
290
|
| `autoCapture` | boolean | `true` | Auto-capture conversations |
|
|
272
291
|
| `autoRecall` | boolean | `true` | Auto-inject relevant memories |
|
|
292
|
+
| `sessionFilter.excludePatterns` | string[] | `[]` | Skip auto-capture/recall for sessions matching any pattern |
|
|
293
|
+
| `sessionFilter.includePatterns` | string[] | `[]` | Only auto-capture/recall sessions matching at least one pattern |
|
|
273
294
|
| `customInstructions` | string | *(see below)* | Custom extraction instructions |
|
|
274
295
|
| `maxCaptureMessages` | integer | `10` | Max messages per auto-capture batch (1-50) |
|
|
275
296
|
|
|
@@ -389,7 +410,10 @@ OpenClaw has an exclusive `memory` slot — only one memory plugin is active at
|
|
|
389
410
|
"my-agent": "U0123ABC"
|
|
390
411
|
},
|
|
391
412
|
"autoCapture": true,
|
|
392
|
-
"autoRecall": true
|
|
413
|
+
"autoRecall": true,
|
|
414
|
+
"sessionFilter": {
|
|
415
|
+
"excludePatterns": ["cron"]
|
|
416
|
+
}
|
|
393
417
|
}
|
|
394
418
|
}
|
|
395
419
|
}
|
package/dist/cli.js
CHANGED
|
@@ -347,9 +347,9 @@ export function registerCommands(cmd, ctx) {
|
|
|
347
347
|
.map((b) => b.text)
|
|
348
348
|
.join("\n");
|
|
349
349
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
350
|
+
text = text.replace(/<relevant-memories>[\s\S]*?<\/relevant-memories>/g, "").trim();
|
|
351
|
+
text = text.replace(/<memory-tools>[\s\S]*?<\/memory-tools>/g, "").trim();
|
|
352
|
+
if (text && text.length >= 5) {
|
|
353
353
|
const roleLabel = role === "user" ? "User" : "Assistant";
|
|
354
354
|
conversationLines.push(`${roleLabel}: ${text}`);
|
|
355
355
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -21,6 +21,10 @@ export type RebacMemoryConfig = {
|
|
|
21
21
|
autoCapture: boolean;
|
|
22
22
|
autoRecall: boolean;
|
|
23
23
|
maxCaptureMessages: number;
|
|
24
|
+
sessionFilter?: {
|
|
25
|
+
excludePatterns?: string[];
|
|
26
|
+
includePatterns?: string[];
|
|
27
|
+
};
|
|
24
28
|
};
|
|
25
29
|
export declare const rebacMemoryConfigSchema: {
|
|
26
30
|
parse(value: unknown): RebacMemoryConfig;
|
package/dist/config.js
CHANGED
|
@@ -25,6 +25,21 @@ function assertAllowedKeys(value, allowed, label) {
|
|
|
25
25
|
throw new Error(`${label} has unknown keys: ${unknown.join(", ")}`);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
function parseSessionFilter(raw) {
|
|
29
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
30
|
+
return undefined;
|
|
31
|
+
const obj = raw;
|
|
32
|
+
assertAllowedKeys(obj, ["excludePatterns", "includePatterns"], "sessionFilter config");
|
|
33
|
+
const excludePatterns = Array.isArray(obj.excludePatterns)
|
|
34
|
+
? obj.excludePatterns.filter((p) => typeof p === "string")
|
|
35
|
+
: undefined;
|
|
36
|
+
const includePatterns = Array.isArray(obj.includePatterns)
|
|
37
|
+
? obj.includePatterns.filter((p) => typeof p === "string")
|
|
38
|
+
: undefined;
|
|
39
|
+
if (!excludePatterns?.length && !includePatterns?.length)
|
|
40
|
+
return undefined;
|
|
41
|
+
return { excludePatterns, includePatterns };
|
|
42
|
+
}
|
|
28
43
|
// ============================================================================
|
|
29
44
|
// Config schema
|
|
30
45
|
// ============================================================================
|
|
@@ -42,7 +57,7 @@ export const rebacMemoryConfigSchema = {
|
|
|
42
57
|
assertAllowedKeys(cfg, [
|
|
43
58
|
"backend", "spicedb",
|
|
44
59
|
"subjectType", "subjectId", "identities",
|
|
45
|
-
"autoCapture", "autoRecall", "maxCaptureMessages",
|
|
60
|
+
"autoCapture", "autoRecall", "maxCaptureMessages", "sessionFilter",
|
|
46
61
|
backendName,
|
|
47
62
|
], "openclaw-memory-rebac config");
|
|
48
63
|
// SpiceDB config (shared)
|
|
@@ -84,6 +99,7 @@ export const rebacMemoryConfigSchema = {
|
|
|
84
99
|
maxCaptureMessages: typeof cfg.maxCaptureMessages === "number" && cfg.maxCaptureMessages > 0
|
|
85
100
|
? cfg.maxCaptureMessages
|
|
86
101
|
: pluginDefaults.maxCaptureMessages,
|
|
102
|
+
sessionFilter: parseSessionFilter(cfg.sessionFilter),
|
|
87
103
|
};
|
|
88
104
|
},
|
|
89
105
|
};
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,26 @@ function sessionGroupId(sessionId) {
|
|
|
34
34
|
function isSessionGroup(groupId) {
|
|
35
35
|
return groupId.startsWith("session-");
|
|
36
36
|
}
|
|
37
|
+
function isSessionAllowed(sessionKey, filter) {
|
|
38
|
+
if (!filter)
|
|
39
|
+
return true;
|
|
40
|
+
if (!sessionKey)
|
|
41
|
+
return true;
|
|
42
|
+
if (filter.excludePatterns?.length) {
|
|
43
|
+
for (const pattern of filter.excludePatterns) {
|
|
44
|
+
if (sessionKey.includes(pattern))
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (filter.includePatterns?.length) {
|
|
49
|
+
for (const pattern of filter.includePatterns) {
|
|
50
|
+
if (sessionKey.includes(pattern))
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
37
57
|
// ============================================================================
|
|
38
58
|
// Plugin Definition
|
|
39
59
|
// ============================================================================
|
|
@@ -460,6 +480,8 @@ const rebacMemoryPlugin = {
|
|
|
460
480
|
const state = getState(ctx?.agentId);
|
|
461
481
|
if (ctx?.sessionKey)
|
|
462
482
|
state.sessionId = ctx.sessionKey;
|
|
483
|
+
if (!isSessionAllowed(ctx?.sessionKey, cfg.sessionFilter))
|
|
484
|
+
return;
|
|
463
485
|
if (!event.prompt || event.prompt.length < 5)
|
|
464
486
|
return;
|
|
465
487
|
try {
|
|
@@ -509,6 +531,8 @@ const rebacMemoryPlugin = {
|
|
|
509
531
|
const state = getState(ctx?.agentId);
|
|
510
532
|
if (ctx?.sessionKey)
|
|
511
533
|
state.sessionId = ctx.sessionKey;
|
|
534
|
+
if (!isSessionAllowed(ctx?.sessionKey, cfg.sessionFilter))
|
|
535
|
+
return;
|
|
512
536
|
if (!event.success || !event.messages || event.messages.length === 0)
|
|
513
537
|
return;
|
|
514
538
|
try {
|
|
@@ -542,10 +566,11 @@ const rebacMemoryPlugin = {
|
|
|
542
566
|
}
|
|
543
567
|
text = textParts.join("\n");
|
|
544
568
|
}
|
|
569
|
+
// Strip injected memory/tool blocks — keep the user's actual content
|
|
570
|
+
text = text.replace(/<relevant-memories>[\s\S]*?<\/relevant-memories>/g, "").trim();
|
|
571
|
+
text = text.replace(/<memory-tools>[\s\S]*?<\/memory-tools>/g, "").trim();
|
|
545
572
|
if (!text || text.length < 5)
|
|
546
573
|
continue;
|
|
547
|
-
if (text.includes("<relevant-memories>"))
|
|
548
|
-
continue;
|
|
549
574
|
const roleLabel = role === "user" ? "User" : "Assistant";
|
|
550
575
|
conversationLines.unshift(`${roleLabel}: ${text}`);
|
|
551
576
|
messageCount++;
|
package/package.json
CHANGED