memory-braid 0.6.0 → 0.6.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memory-braid",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "OpenClaw memory plugin that augments local memory with Mem0 capture and recall.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/capture.ts CHANGED
@@ -17,9 +17,70 @@ function asRecord(value: unknown): Record<string, unknown> {
17
17
  return value as Record<string, unknown>;
18
18
  }
19
19
 
20
+ function extractStructuredTextCandidate(value: unknown, depth = 0): string {
21
+ if (depth > 5) {
22
+ return "";
23
+ }
24
+ if (typeof value === "string") {
25
+ return normalizeWhitespace(value);
26
+ }
27
+ if (!value || typeof value !== "object") {
28
+ return "";
29
+ }
30
+ if (Array.isArray(value)) {
31
+ const parts = value
32
+ .map((entry) => extractStructuredTextCandidate(entry, depth + 1))
33
+ .filter(Boolean);
34
+ return normalizeWhitespace(parts.join(" "));
35
+ }
36
+
37
+ const record = value as Record<string, unknown>;
38
+ const directText = typeof record.text === "string" ? normalizeWhitespace(record.text) : "";
39
+ if (directText) {
40
+ return directText;
41
+ }
42
+ const caption = typeof record.caption === "string" ? normalizeWhitespace(record.caption) : "";
43
+ if (caption) {
44
+ return caption;
45
+ }
46
+
47
+ const nestedCandidates = [
48
+ record.message,
49
+ record.data,
50
+ record.payload,
51
+ record.update,
52
+ record.edited_message,
53
+ record.channel_post,
54
+ record.callback_query,
55
+ ];
56
+ for (const candidate of nestedCandidates) {
57
+ const extracted = extractStructuredTextCandidate(candidate, depth + 1);
58
+ if (extracted) {
59
+ return extracted;
60
+ }
61
+ }
62
+
63
+ return "";
64
+ }
65
+
66
+ export function extractStructuredTextFromString(content: string): string | undefined {
67
+ const normalized = normalizeWhitespace(content);
68
+ if (!normalized || !/^[{\[]/.test(normalized)) {
69
+ return undefined;
70
+ }
71
+
72
+ try {
73
+ const parsed = JSON.parse(normalized) as unknown;
74
+ const extracted = extractStructuredTextCandidate(parsed);
75
+ return extracted || undefined;
76
+ } catch {
77
+ return undefined;
78
+ }
79
+ }
80
+
20
81
  export function extractHookMessageText(content: unknown): string {
21
82
  if (typeof content === "string") {
22
- return normalizeWhitespace(content);
83
+ return extractStructuredTextFromString(content) ?? normalizeWhitespace(content);
23
84
  }
24
85
  if (!Array.isArray(content)) {
25
86
  return "";
@@ -32,7 +93,8 @@ export function extractHookMessageText(content: unknown): string {
32
93
  }
33
94
  const item = block as { type?: unknown; text?: unknown };
34
95
  if (item.type === "text" && typeof item.text === "string") {
35
- const normalized = normalizeWhitespace(item.text);
96
+ const normalized =
97
+ extractStructuredTextFromString(item.text) ?? normalizeWhitespace(item.text);
36
98
  if (normalized) {
37
99
  parts.push(normalized);
38
100
  }
package/src/extract.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { normalizeForHash, normalizeWhitespace, sha256 } from "./chunking.js";
2
2
  import type { MemoryBraidConfig } from "./config.js";
3
- import { isLikelyTranscriptLikeText, isOversizedAtomicMemory } from "./capture.js";
3
+ import {
4
+ extractStructuredTextFromString,
5
+ isLikelyTranscriptLikeText,
6
+ isOversizedAtomicMemory,
7
+ } from "./capture.js";
4
8
  import { MemoryBraidLogger } from "./logger.js";
5
9
  import type { ExtractedCandidate } from "./types.js";
6
10
 
@@ -47,7 +51,7 @@ function isLikelyFeedOrImportedText(text: string): boolean {
47
51
 
48
52
  function extractMessageText(content: unknown): string {
49
53
  if (typeof content === "string") {
50
- return normalizeWhitespace(content);
54
+ return extractStructuredTextFromString(content) ?? normalizeWhitespace(content);
51
55
  }
52
56
  if (!Array.isArray(content)) {
53
57
  return "";
@@ -59,7 +63,8 @@ function extractMessageText(content: unknown): string {
59
63
  }
60
64
  const item = block as { type?: unknown; text?: unknown };
61
65
  if (item.type === "text" && typeof item.text === "string") {
62
- const normalized = normalizeWhitespace(item.text);
66
+ const normalized =
67
+ extractStructuredTextFromString(item.text) ?? normalizeWhitespace(item.text);
63
68
  if (normalized) {
64
69
  parts.push(normalized);
65
70
  }
package/src/index.ts CHANGED
@@ -183,6 +183,26 @@ function resolveLatestUserTurnSignature(messages?: unknown[]): string | undefine
183
183
  return undefined;
184
184
  }
185
185
 
186
+ function resolveLatestUserTurnText(messages?: unknown[]): string | undefined {
187
+ if (!Array.isArray(messages) || messages.length === 0) {
188
+ return undefined;
189
+ }
190
+
191
+ const normalized = normalizeHookMessages(messages);
192
+ for (let i = normalized.length - 1; i >= 0; i -= 1) {
193
+ const message = normalized[i];
194
+ if (!message || message.role !== "user") {
195
+ continue;
196
+ }
197
+ const text = normalizeWhitespace(message.text);
198
+ if (!text) {
199
+ continue;
200
+ }
201
+ return text;
202
+ }
203
+ return undefined;
204
+ }
205
+
186
206
  function resolvePromptTurnSignature(prompt: string): string | undefined {
187
207
  const normalized = normalizeForHash(prompt);
188
208
  if (!normalized) {
@@ -2248,7 +2268,8 @@ const memoryBraidPlugin = {
2248
2268
  return baseResult;
2249
2269
  }
2250
2270
 
2251
- const recallQuery = sanitizeRecallQuery(event.prompt);
2271
+ const latestUserTurnText = resolveLatestUserTurnText(event.messages);
2272
+ const recallQuery = sanitizeRecallQuery(latestUserTurnText ?? event.prompt);
2252
2273
  if (!recallQuery) {
2253
2274
  return baseResult;
2254
2275
  }