@contextableai/openclaw-memory-rebac 0.3.7 → 0.3.8
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/dist/index.d.ts +6 -0
- package/dist/index.js +27 -4
- package/docker/graphiti/Dockerfile +4 -2
- package/docker/graphiti/startup.py +25 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,12 @@
|
|
|
16
16
|
* falling back to config-level subjectType/subjectId when agentId is absent.
|
|
17
17
|
*/
|
|
18
18
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
19
|
+
/**
|
|
20
|
+
* Strip OpenClaw envelope metadata from message text before Graphiti ingestion.
|
|
21
|
+
* Removes channel headers, sender/message-id meta lines, and memory injection
|
|
22
|
+
* blocks that would pollute entity extraction.
|
|
23
|
+
*/
|
|
24
|
+
export declare function stripEnvelopeMetadata(text: string): string;
|
|
19
25
|
declare const rebacMemoryPlugin: {
|
|
20
26
|
id: string;
|
|
21
27
|
name: string;
|
package/dist/index.js
CHANGED
|
@@ -55,6 +55,30 @@ function isSessionAllowed(sessionKey, filter) {
|
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
// ============================================================================
|
|
58
|
+
// Content sanitization
|
|
59
|
+
// ============================================================================
|
|
60
|
+
/**
|
|
61
|
+
* Strip OpenClaw envelope metadata from message text before Graphiti ingestion.
|
|
62
|
+
* Removes channel headers, sender/message-id meta lines, and memory injection
|
|
63
|
+
* blocks that would pollute entity extraction.
|
|
64
|
+
*/
|
|
65
|
+
export function stripEnvelopeMetadata(text) {
|
|
66
|
+
let result = text;
|
|
67
|
+
// Strip envelope header: [ChannelName ...metadata...] at start of line
|
|
68
|
+
// Matches: [Telegram Dev Chat +5m 2025-01-02T03:04Z] body
|
|
69
|
+
result = result.replace(/^\[[A-Z][^\]\n]*\]\s*/gm, "");
|
|
70
|
+
// Strip [from: SenderLabel] trailer lines
|
|
71
|
+
result = result.replace(/^\[from:\s*[^\]]*\]\s*$/gm, "");
|
|
72
|
+
// Strip [message_id: ...] hint lines
|
|
73
|
+
result = result.replace(/^\[message_id:\s*[^\]]*\]\s*$/gm, "");
|
|
74
|
+
// Strip memory injection blocks
|
|
75
|
+
result = result.replace(/<relevant-memories>[\s\S]*?<\/relevant-memories>/g, "");
|
|
76
|
+
result = result.replace(/<memory-tools>[\s\S]*?<\/memory-tools>/g, "");
|
|
77
|
+
// Collapse excess blank lines and trim
|
|
78
|
+
result = result.replace(/\n{3,}/g, "\n\n").trim();
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
// ============================================================================
|
|
58
82
|
// Plugin Definition
|
|
59
83
|
// ============================================================================
|
|
60
84
|
const rebacMemoryPlugin = {
|
|
@@ -566,9 +590,8 @@ const rebacMemoryPlugin = {
|
|
|
566
590
|
}
|
|
567
591
|
text = textParts.join("\n");
|
|
568
592
|
}
|
|
569
|
-
// Strip injected
|
|
570
|
-
text = text
|
|
571
|
-
text = text.replace(/<memory-tools>[\s\S]*?<\/memory-tools>/g, "").trim();
|
|
593
|
+
// Strip envelope metadata and injected blocks — keep the user's actual content
|
|
594
|
+
text = stripEnvelopeMetadata(text);
|
|
572
595
|
if (!text || text.length < 5)
|
|
573
596
|
continue;
|
|
574
597
|
const roleLabel = role === "user" ? "User" : "Assistant";
|
|
@@ -660,7 +683,7 @@ const rebacMemoryPlugin = {
|
|
|
660
683
|
}
|
|
661
684
|
return "";
|
|
662
685
|
};
|
|
663
|
-
const userMsg = extractText(lastUserMsg);
|
|
686
|
+
const userMsg = stripEnvelopeMetadata(extractText(lastUserMsg));
|
|
664
687
|
const assistantMsg = extractText(lastAssistMsg);
|
|
665
688
|
if (userMsg && assistantMsg) {
|
|
666
689
|
backend.enrichSession({
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
# 1. Install sentence-transformers for BGE reranker
|
|
7
7
|
# 2. Overlay per-component config + startup to wire separate clients
|
|
8
8
|
#
|
|
9
|
-
# UPGRADE AUDIT (vs upstream getzep/graphiti v0.28.2, audited 2026-03-
|
|
10
|
-
# Overlay patches in startup.py —
|
|
9
|
+
# UPGRADE AUDIT (vs upstream getzep/graphiti v0.28.2, audited 2026-03-24):
|
|
10
|
+
# Overlay patches in startup.py — 6 of 7 still needed:
|
|
11
11
|
# [NEEDED] AsyncWorker crash-on-error recovery (startup.py:109-126)
|
|
12
12
|
# [NEEDED] Neo4j nested attribute sanitization (startup.py:128-250)
|
|
13
13
|
# [SAFE] None-index extract_edges fix (startup.py:252-298)
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
# [NEEDED] IS_DUPLICATE_OF edge filtering (startup.py:152-169,216-227,310-318)
|
|
16
16
|
# [NEEDED] Self-referential edge filtering (startup.py:228-239)
|
|
17
17
|
# [NEEDED] Singleton client / per-request fix (startup.py:38-87)
|
|
18
|
+
# [NEEDED] resolve_extracted_edge IndexError guard (startup.py:325-349)
|
|
19
|
+
# — fixed upstream v0.28.2+; no Docker image published beyond 0.22.0
|
|
18
20
|
###############################################################################
|
|
19
21
|
|
|
20
22
|
FROM zepai/graphiti:0.22.0
|
|
@@ -322,6 +322,31 @@ def patch():
|
|
|
322
322
|
# Patch the local binding in graphiti.py
|
|
323
323
|
graphiti_mod.extract_edges = safe_extract_edges
|
|
324
324
|
|
|
325
|
+
# -- Guard resolve_extracted_edge against IndexError from out-of-bounds
|
|
326
|
+
# contradicted_facts indices (issue #22) --
|
|
327
|
+
# The LLM sometimes returns fact indices that exceed the existing_edges list
|
|
328
|
+
# length, crashing the list comprehension. Upstream v0.28.2+ adds bounds
|
|
329
|
+
# checking; this patch provides equivalent safety for pinned v0.22.0.
|
|
330
|
+
original_resolve_extracted_edge = edge_ops_mod.resolve_extracted_edge
|
|
331
|
+
|
|
332
|
+
async def safe_resolve_extracted_edge(*args, **kwargs):
|
|
333
|
+
try:
|
|
334
|
+
return await original_resolve_extracted_edge(*args, **kwargs)
|
|
335
|
+
except IndexError as e:
|
|
336
|
+
logger.warning(
|
|
337
|
+
"resolve_extracted_edge: IndexError caught (out-of-bounds "
|
|
338
|
+
"contradicted_facts index): %s — returning edge as-is with "
|
|
339
|
+
"no invalidations",
|
|
340
|
+
e,
|
|
341
|
+
)
|
|
342
|
+
# args[1] is extracted_edge per the function signature
|
|
343
|
+
extracted_edge = args[1] if len(args) > 1 else kwargs.get("extracted_edge")
|
|
344
|
+
if extracted_edge is None:
|
|
345
|
+
raise
|
|
346
|
+
return (extracted_edge, [], [])
|
|
347
|
+
|
|
348
|
+
edge_ops_mod.resolve_extracted_edge = safe_resolve_extracted_edge
|
|
349
|
+
|
|
325
350
|
return app
|
|
326
351
|
|
|
327
352
|
|
package/package.json
CHANGED