@icex-labs/openclaw-memory-engine 5.0.2 → 5.1.0
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/extras/migrate-legacy.mjs +18 -1
- package/index.js +1 -1
- package/lib/quality.js +39 -3
- package/package.json +1 -1
- package/setup.sh +19 -0
|
@@ -140,9 +140,26 @@ for (const { path, tag } of files) {
|
|
|
140
140
|
continue;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
// Infer date from filename (e.g., 2026-03-28.md → 2026-03-28, 2026-W13.md → week date)
|
|
144
|
+
const dateMatch = basename(path).match(/^(\d{4}-\d{2}-\d{2})/);
|
|
145
|
+
const weekMatch = basename(path).match(/^(\d{4})-W(\d{2})/);
|
|
146
|
+
let inferredTs;
|
|
147
|
+
if (dateMatch) {
|
|
148
|
+
inferredTs = dateMatch[1] + "T12:00:00Z";
|
|
149
|
+
} else if (weekMatch) {
|
|
150
|
+
// Approximate: week number × 7 days from Jan 1
|
|
151
|
+
const year = parseInt(weekMatch[1]);
|
|
152
|
+
const week = parseInt(weekMatch[2]);
|
|
153
|
+
const jan1 = new Date(year, 0, 1);
|
|
154
|
+
const weekDate = new Date(jan1.getTime() + (week - 1) * 7 * 86400000);
|
|
155
|
+
inferredTs = weekDate.toISOString();
|
|
156
|
+
} else {
|
|
157
|
+
inferredTs = new Date().toISOString();
|
|
158
|
+
}
|
|
159
|
+
|
|
143
160
|
const record = {
|
|
144
161
|
id: `arch-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
145
|
-
ts:
|
|
162
|
+
ts: inferredTs,
|
|
146
163
|
last_accessed: null,
|
|
147
164
|
access_count: 0,
|
|
148
165
|
importance: 5,
|
package/index.js
CHANGED
|
@@ -702,7 +702,7 @@ export default definePluginEntry({
|
|
|
702
702
|
async execute(_id, params) {
|
|
703
703
|
const wsp = ws(agentId, params);
|
|
704
704
|
try {
|
|
705
|
-
const result = runQualityPass(wsp, {
|
|
705
|
+
const result = await runQualityPass(wsp, {
|
|
706
706
|
skipGraph: params.skip_graph || false,
|
|
707
707
|
skipEpisodes: params.skip_episodes || false,
|
|
708
708
|
});
|
package/lib/quality.js
CHANGED
|
@@ -67,12 +67,18 @@ export async function runQualityPass(ws, options = {}) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
|
-
* Generate episode summaries from
|
|
70
|
+
* Generate episode summaries from records.
|
|
71
|
+
* Strategy 1: group by date (works when ts reflects original dates)
|
|
72
|
+
* Strategy 2: group by entity/topic (fallback when all ts are same day, e.g., after migration)
|
|
71
73
|
*/
|
|
72
74
|
function generateEpisodesFromRecords(ws, records) {
|
|
73
75
|
const episodes = loadEpisodes(ws);
|
|
76
|
+
const existingTopics = new Set(episodes.flatMap((e) => e.topics || []));
|
|
74
77
|
const existingDates = new Set(episodes.map((e) => e.ts?.slice(0, 10)));
|
|
75
78
|
|
|
79
|
+
let generated = 0;
|
|
80
|
+
|
|
81
|
+
// Strategy 1: by date
|
|
76
82
|
const byDate = {};
|
|
77
83
|
for (const r of records) {
|
|
78
84
|
if (!r.ts) continue;
|
|
@@ -81,14 +87,15 @@ function generateEpisodesFromRecords(ws, records) {
|
|
|
81
87
|
byDate[date].push(r);
|
|
82
88
|
}
|
|
83
89
|
|
|
84
|
-
let generated = 0;
|
|
85
90
|
for (const [date, dayRecords] of Object.entries(byDate)) {
|
|
86
91
|
if (existingDates.has(date) || dayRecords.length < 3) continue;
|
|
92
|
+
// Skip if most records share the same date (migration artifact)
|
|
93
|
+
if (dayRecords.length > records.length * 0.5) continue;
|
|
87
94
|
|
|
88
95
|
const topics = [...new Set(dayRecords.map((r) => r.entity).filter((e) => e && e !== "general"))];
|
|
89
96
|
const topContent = dayRecords
|
|
90
97
|
.sort((a, b) => (b.importance || 5) - (a.importance || 5))
|
|
91
|
-
.slice(0,
|
|
98
|
+
.slice(0, 3)
|
|
92
99
|
.map((r) => r.content.slice(0, 80))
|
|
93
100
|
.join("; ");
|
|
94
101
|
|
|
@@ -103,6 +110,35 @@ function generateEpisodesFromRecords(ws, records) {
|
|
|
103
110
|
generated++;
|
|
104
111
|
}
|
|
105
112
|
|
|
113
|
+
// Strategy 2: by entity (fallback for migration data with same-day ts)
|
|
114
|
+
const byEntity = {};
|
|
115
|
+
for (const r of records) {
|
|
116
|
+
const e = r.entity || "general";
|
|
117
|
+
if (e === "general") continue;
|
|
118
|
+
if (!byEntity[e]) byEntity[e] = [];
|
|
119
|
+
byEntity[e].push(r);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
for (const [entity, recs] of Object.entries(byEntity)) {
|
|
123
|
+
if (recs.length < 5) continue;
|
|
124
|
+
if (existingTopics.has(entity)) continue;
|
|
125
|
+
|
|
126
|
+
const top = recs
|
|
127
|
+
.sort((a, b) => (b.importance || 5) - (a.importance || 5))
|
|
128
|
+
.slice(0, 3)
|
|
129
|
+
.map((r) => r.content.slice(0, 80));
|
|
130
|
+
|
|
131
|
+
saveEpisode(ws, {
|
|
132
|
+
summary: `[${entity}] ${top.join("; ")}`,
|
|
133
|
+
decisions: [],
|
|
134
|
+
mood: "",
|
|
135
|
+
topics: [entity],
|
|
136
|
+
participants: [],
|
|
137
|
+
source: "topic-summary",
|
|
138
|
+
});
|
|
139
|
+
generated++;
|
|
140
|
+
}
|
|
141
|
+
|
|
106
142
|
return generated;
|
|
107
143
|
}
|
|
108
144
|
|
package/package.json
CHANGED
package/setup.sh
CHANGED
|
@@ -149,6 +149,25 @@ if command -v node &>/dev/null && [ -f "$PLUGIN_DIR/extras/migrate-legacy.mjs" ]
|
|
|
149
149
|
fi
|
|
150
150
|
fi
|
|
151
151
|
|
|
152
|
+
# --- 3c. Upgrade: run v5.0 embedding classification if not done yet ---
|
|
153
|
+
if [ -f "$MEMORY_DIR/archival.jsonl" ] && [ ! -f "$MEMORY_DIR/classifier-anchors.json" ]; then
|
|
154
|
+
archival_count=$(wc -l < "$MEMORY_DIR/archival.jsonl" | tr -d ' ')
|
|
155
|
+
if [ "$archival_count" -gt 0 ]; then
|
|
156
|
+
echo ""
|
|
157
|
+
echo "📊 Upgrade detected: running v5.0 embedding-based classification..."
|
|
158
|
+
echo " This replaces keyword-based entity/importance with semantic classification."
|
|
159
|
+
if command -v openclaw &>/dev/null; then
|
|
160
|
+
# Use the agent to run memory_quality (needs gateway running)
|
|
161
|
+
openclaw agent --agent main -m "memory_quality" --timeout 120 2>&1 | tail -3 || {
|
|
162
|
+
echo "⚠️ Quality pass via agent failed (gateway may not be running)."
|
|
163
|
+
echo " Run manually after restart: openclaw agent -m 'memory_quality'"
|
|
164
|
+
}
|
|
165
|
+
else
|
|
166
|
+
echo "⚠️ openclaw CLI not found. Run after install: openclaw agent -m 'memory_quality'"
|
|
167
|
+
fi
|
|
168
|
+
fi
|
|
169
|
+
fi
|
|
170
|
+
|
|
152
171
|
# --- 4. Install memory-maintenance.sh ---
|
|
153
172
|
SCRIPTS_DIR="$WORKSPACE/scripts"
|
|
154
173
|
mkdir -p "$SCRIPTS_DIR"
|