@christopherlittle51/postclaw 1.0.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/.env.example +4 -0
- package/LICENSE +15 -0
- package/README.md +731 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +506 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/validation.d.ts +81 -0
- package/dist/schemas/validation.d.ts.map +1 -0
- package/dist/schemas/validation.js +27 -0
- package/dist/schemas/validation.js.map +1 -0
- package/dist/scripts/bootstrap_persona.d.ts +20 -0
- package/dist/scripts/bootstrap_persona.d.ts.map +1 -0
- package/dist/scripts/bootstrap_persona.js +150 -0
- package/dist/scripts/bootstrap_persona.js.map +1 -0
- package/dist/scripts/bootstrap_tools.d.ts +2 -0
- package/dist/scripts/bootstrap_tools.d.ts.map +1 -0
- package/dist/scripts/bootstrap_tools.js +67 -0
- package/dist/scripts/bootstrap_tools.js.map +1 -0
- package/dist/scripts/setup-db.d.ts +28 -0
- package/dist/scripts/setup-db.d.ts.map +1 -0
- package/dist/scripts/setup-db.js +539 -0
- package/dist/scripts/setup-db.js.map +1 -0
- package/dist/scripts/sleep_cycle.d.ts +32 -0
- package/dist/scripts/sleep_cycle.d.ts.map +1 -0
- package/dist/scripts/sleep_cycle.js +452 -0
- package/dist/scripts/sleep_cycle.js.map +1 -0
- package/dist/services/db.d.ts +28 -0
- package/dist/services/db.d.ts.map +1 -0
- package/dist/services/db.js +93 -0
- package/dist/services/db.js.map +1 -0
- package/dist/services/memoryService.d.ts +75 -0
- package/dist/services/memoryService.d.ts.map +1 -0
- package/dist/services/memoryService.js +391 -0
- package/dist/services/memoryService.js.map +1 -0
- package/dist/test-db.d.ts +8 -0
- package/dist/test-db.d.ts.map +1 -0
- package/dist/test-db.js +94 -0
- package/dist/test-db.js.map +1 -0
- package/dist/test-memory.d.ts +2 -0
- package/dist/test-memory.d.ts.map +1 -0
- package/dist/test-memory.js +79 -0
- package/dist/test-memory.js.map +1 -0
- package/openclaw.plugin.json +37 -0
- package/package.json +49 -0
- package/schemas/db.sql +371 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PostClaw Sleep Cycle — Knowledge Graph Maintenance Agent
|
|
4
|
+
*
|
|
5
|
+
* Runs 4 maintenance phases on the memory database:
|
|
6
|
+
* 1. Episodic Consolidation — extract durable facts from short-term memory
|
|
7
|
+
* 2. Duplicate Detection — find and merge near-duplicate semantic memories
|
|
8
|
+
* 3. Low-Value Cleanup — archive stale, unaccessed memories
|
|
9
|
+
* 4. Link Discovery — auto-discover and create knowledge graph edges
|
|
10
|
+
*
|
|
11
|
+
* Usage (via OpenClaw CLI):
|
|
12
|
+
* openclaw postclaw sleep [--agent-id <id>]
|
|
13
|
+
*
|
|
14
|
+
* Also runs as a background service on a configurable interval when the
|
|
15
|
+
* gateway is running (default: every 6 hours).
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.runSleepCycle = runSleepCycle;
|
|
19
|
+
exports.startService = startService;
|
|
20
|
+
exports.stopService = stopService;
|
|
21
|
+
const db_js_1 = require("../services/db.js");
|
|
22
|
+
const memoryService_js_1 = require("../services/memoryService.js");
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// CONFIGURATION — All thresholds are easily tunable here
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// Phase 1: Episodic consolidation
|
|
27
|
+
const EPISODIC_BATCH_LIMIT = 100;
|
|
28
|
+
// Phase 2: Duplicate detection
|
|
29
|
+
const DUPLICATE_SIMILARITY_THRESHOLD = 0.80;
|
|
30
|
+
const DUPLICATE_SCAN_LIMIT = 200;
|
|
31
|
+
// Phase 3: Low-value cleanup
|
|
32
|
+
const LOW_VALUE_AGE_DAYS = 7;
|
|
33
|
+
const LOW_VALUE_PROTECTED_TIERS = ['permanent', 'stable'];
|
|
34
|
+
// Phase 4: Link discovery
|
|
35
|
+
const LINK_SIMILARITY_MIN = 0.65;
|
|
36
|
+
const LINK_SIMILARITY_MAX = 0.92;
|
|
37
|
+
const LINK_CANDIDATES_PER_MEMORY = 5;
|
|
38
|
+
const LINK_BATCH_SIZE = 20;
|
|
39
|
+
const LINK_SCAN_LIMIT = 50;
|
|
40
|
+
// Background service
|
|
41
|
+
const DEFAULT_INTERVAL_HOURS = 6;
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// UTILITIES
|
|
44
|
+
// =============================================================================
|
|
45
|
+
async function callLLM(systemPrompt, userPrompt, llmUrl, llmModel, temperature = 0.1) {
|
|
46
|
+
const baseUrl = llmUrl.replace(/\/v1\/?$/, "");
|
|
47
|
+
const res = await fetch(`${baseUrl}/v1/chat/completions`, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: { "Content-Type": "application/json" },
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
model: llmModel,
|
|
52
|
+
messages: [
|
|
53
|
+
{ role: "system", content: systemPrompt },
|
|
54
|
+
{ role: "user", content: userPrompt },
|
|
55
|
+
],
|
|
56
|
+
temperature,
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
if (!res.ok) {
|
|
60
|
+
throw new Error(`LLM request failed: ${res.status} ${res.statusText}`);
|
|
61
|
+
}
|
|
62
|
+
const data = await res.json();
|
|
63
|
+
let jsonString = data.choices[0].message.content.trim();
|
|
64
|
+
// Strip reasoning blocks from qwen3.5 output
|
|
65
|
+
jsonString = jsonString.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
66
|
+
if (jsonString.startsWith("```json"))
|
|
67
|
+
jsonString = jsonString.replace(/^```json\n/, "").replace(/\n```$/, "");
|
|
68
|
+
if (jsonString.startsWith("```"))
|
|
69
|
+
jsonString = jsonString.replace(/^```\n/, "").replace(/\n```$/, "");
|
|
70
|
+
return jsonString;
|
|
71
|
+
}
|
|
72
|
+
// =============================================================================
|
|
73
|
+
// PHASE 1: EPISODIC CONSOLIDATION
|
|
74
|
+
// =============================================================================
|
|
75
|
+
async function phaseConsolidateEpisodic(agentId, llmUrl, llmModel) {
|
|
76
|
+
console.log(`\n[PHASE 1] Episodic Memory Consolidation`);
|
|
77
|
+
console.log(`─────────────────────────────────────────`);
|
|
78
|
+
const sql = (0, db_js_1.getSql)();
|
|
79
|
+
const episodes = await sql.begin(async (tx) => {
|
|
80
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
81
|
+
return await tx `
|
|
82
|
+
SELECT id, event_type, event_summary, created_at
|
|
83
|
+
FROM memory_episodic
|
|
84
|
+
WHERE agent_id = ${agentId} AND is_archived = false
|
|
85
|
+
ORDER BY created_at ASC
|
|
86
|
+
LIMIT ${EPISODIC_BATCH_LIMIT};
|
|
87
|
+
`;
|
|
88
|
+
});
|
|
89
|
+
if (episodes.length === 0) {
|
|
90
|
+
console.log(`[PHASE 1] No new episodic memories to process.`);
|
|
91
|
+
return 0;
|
|
92
|
+
}
|
|
93
|
+
console.log(`[PHASE 1] Found ${episodes.length} episodic events to consolidate.`);
|
|
94
|
+
const transcript = episodes
|
|
95
|
+
.map((e) => `[${e.created_at}] [${e.event_type.toUpperCase()}]: ${e.event_summary}`)
|
|
96
|
+
.join("\n");
|
|
97
|
+
const systemPrompt = `
|
|
98
|
+
You are the subconscious memory consolidation engine for an AI assistant.
|
|
99
|
+
Your job is to review the following chronological transcript of the agent's recent short-term memory (user prompts and tool executions).
|
|
100
|
+
|
|
101
|
+
Extract ONLY durable, long-term facts that the agent should remember forever.
|
|
102
|
+
- Ignore casual banter, specific temporary weather lookups, or transient errors.
|
|
103
|
+
- DO extract user preferences, API keys, infrastructure details, or new project rules.
|
|
104
|
+
|
|
105
|
+
Output your response EXCLUSIVELY as a JSON object matching this schema:
|
|
106
|
+
{
|
|
107
|
+
"session_summary": "A brief 2-sentence summary of what happened during this timeframe.",
|
|
108
|
+
"extracted_durable_facts": ["fact 1", "fact 2"]
|
|
109
|
+
}
|
|
110
|
+
Do not use markdown formatting.
|
|
111
|
+
`;
|
|
112
|
+
const jsonString = await callLLM(systemPrompt, `Here is the recent episodic transcript to analyze:\n\n${transcript}`, llmUrl, llmModel);
|
|
113
|
+
const result = JSON.parse(jsonString);
|
|
114
|
+
console.log(`[PHASE 1] Extracted ${result.extracted_durable_facts.length} permanent facts.`);
|
|
115
|
+
console.log(`[PHASE 1] Session Summary: ${result.session_summary}`);
|
|
116
|
+
await sql.begin(async (tx) => {
|
|
117
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
118
|
+
for (const fact of result.extracted_durable_facts) {
|
|
119
|
+
const embedding = await (0, db_js_1.getEmbedding)(fact);
|
|
120
|
+
const encoder = new TextEncoder();
|
|
121
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", encoder.encode(fact));
|
|
122
|
+
const contentHash = Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
123
|
+
await tx `
|
|
124
|
+
INSERT INTO memory_semantic (
|
|
125
|
+
agent_id, access_scope, content, content_hash, embedding, embedding_model, tier
|
|
126
|
+
) VALUES (
|
|
127
|
+
${agentId}, 'private', ${fact}, ${contentHash}, ${JSON.stringify(embedding)}, 'nomic-embed-text-v2-moe', 'permanent'
|
|
128
|
+
) ON CONFLICT (agent_id, content_hash) DO NOTHING;
|
|
129
|
+
`;
|
|
130
|
+
console.log(`[PHASE 1] -> Saved durable fact: "${fact}"`);
|
|
131
|
+
}
|
|
132
|
+
const episodeIds = episodes.map((e) => e.id);
|
|
133
|
+
await tx `
|
|
134
|
+
UPDATE memory_episodic
|
|
135
|
+
SET is_archived = true
|
|
136
|
+
WHERE id IN ${sql(episodeIds)}
|
|
137
|
+
`;
|
|
138
|
+
});
|
|
139
|
+
console.log(`[PHASE 1] Archived ${episodes.length} short-term memories. Consolidation complete.`);
|
|
140
|
+
return result.extracted_durable_facts.length;
|
|
141
|
+
}
|
|
142
|
+
// =============================================================================
|
|
143
|
+
// PHASE 2: DUPLICATE DETECTION & MERGE
|
|
144
|
+
// =============================================================================
|
|
145
|
+
async function phaseDuplicateDetection(agentId) {
|
|
146
|
+
console.log(`\n[PHASE 2] Duplicate Detection & Merge`);
|
|
147
|
+
console.log(`─────────────────────────────────────────`);
|
|
148
|
+
console.log(`[PHASE 2] Similarity threshold: ${DUPLICATE_SIMILARITY_THRESHOLD}`);
|
|
149
|
+
const sql = (0, db_js_1.getSql)();
|
|
150
|
+
const memories = await sql.begin(async (tx) => {
|
|
151
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
152
|
+
return await tx `
|
|
153
|
+
SELECT id, content, embedding, usefulness_score, access_count, created_at
|
|
154
|
+
FROM memory_semantic
|
|
155
|
+
WHERE agent_id = ${agentId} AND is_archived = false
|
|
156
|
+
ORDER BY created_at DESC
|
|
157
|
+
LIMIT ${DUPLICATE_SCAN_LIMIT};
|
|
158
|
+
`;
|
|
159
|
+
});
|
|
160
|
+
if (memories.length < 2) {
|
|
161
|
+
console.log(`[PHASE 2] Not enough memories to scan for duplicates (${memories.length}).`);
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
console.log(`[PHASE 2] Scanning ${memories.length} memories for duplicates...`);
|
|
165
|
+
let mergedCount = 0;
|
|
166
|
+
const archivedIds = new Set();
|
|
167
|
+
await sql.begin(async (tx) => {
|
|
168
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
169
|
+
for (let i = 0; i < memories.length; i++) {
|
|
170
|
+
const source = memories[i];
|
|
171
|
+
if (archivedIds.has(source.id))
|
|
172
|
+
continue;
|
|
173
|
+
const duplicates = await tx `
|
|
174
|
+
SELECT id, content, usefulness_score, access_count
|
|
175
|
+
FROM memory_semantic
|
|
176
|
+
WHERE agent_id = ${agentId}
|
|
177
|
+
AND is_archived = false
|
|
178
|
+
AND id != ${source.id}
|
|
179
|
+
AND 1 - (embedding <=> ${source.embedding}) > ${DUPLICATE_SIMILARITY_THRESHOLD}
|
|
180
|
+
ORDER BY usefulness_score DESC, access_count DESC
|
|
181
|
+
LIMIT 10;
|
|
182
|
+
`;
|
|
183
|
+
if (duplicates.length === 0)
|
|
184
|
+
continue;
|
|
185
|
+
const allCandidates = [source, ...duplicates];
|
|
186
|
+
allCandidates.sort((a, b) => {
|
|
187
|
+
const scoreA = (a.usefulness_score || 0) + (a.access_count || 0) * 0.1;
|
|
188
|
+
const scoreB = (b.usefulness_score || 0) + (b.access_count || 0) * 0.1;
|
|
189
|
+
return scoreB - scoreA;
|
|
190
|
+
});
|
|
191
|
+
const survivor = allCandidates[0];
|
|
192
|
+
const losers = allCandidates.slice(1);
|
|
193
|
+
for (const loser of losers) {
|
|
194
|
+
if (archivedIds.has(loser.id))
|
|
195
|
+
continue;
|
|
196
|
+
await tx `
|
|
197
|
+
UPDATE memory_semantic
|
|
198
|
+
SET is_archived = true, superseded_by = ${survivor.id}
|
|
199
|
+
WHERE id = ${loser.id} AND agent_id = ${agentId};
|
|
200
|
+
`;
|
|
201
|
+
archivedIds.add(loser.id);
|
|
202
|
+
mergedCount++;
|
|
203
|
+
console.log(`[PHASE 2] -> Merged duplicate: "${loser.content.substring(0, 60)}..." → survivor ${survivor.id.substring(0, 8)}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
console.log(`[PHASE 2] Merged ${mergedCount} duplicate memories.`);
|
|
208
|
+
return mergedCount;
|
|
209
|
+
}
|
|
210
|
+
// =============================================================================
|
|
211
|
+
// PHASE 3: LOW-VALUE ENTRY CLEANUP
|
|
212
|
+
// =============================================================================
|
|
213
|
+
async function phaseLowValueCleanup(agentId) {
|
|
214
|
+
console.log(`\n[PHASE 3] Low-Value Entry Cleanup`);
|
|
215
|
+
console.log(`─────────────────────────────────────────`);
|
|
216
|
+
console.log(`[PHASE 3] Archiving memories with 0 access older than ${LOW_VALUE_AGE_DAYS} days (protecting: ${LOW_VALUE_PROTECTED_TIERS.join(', ')})`);
|
|
217
|
+
const sql = (0, db_js_1.getSql)();
|
|
218
|
+
const result = await sql.begin(async (tx) => {
|
|
219
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
220
|
+
const staleMemories = await tx `
|
|
221
|
+
SELECT id, content, tier, access_count, created_at
|
|
222
|
+
FROM memory_semantic
|
|
223
|
+
WHERE agent_id = ${agentId}
|
|
224
|
+
AND is_archived = false
|
|
225
|
+
AND access_count = 0
|
|
226
|
+
AND created_at < NOW() - INTERVAL '1 day' * ${LOW_VALUE_AGE_DAYS}
|
|
227
|
+
AND tier NOT IN ('permanent', 'stable')
|
|
228
|
+
ORDER BY created_at ASC;
|
|
229
|
+
`;
|
|
230
|
+
if (staleMemories.length === 0) {
|
|
231
|
+
return 0;
|
|
232
|
+
}
|
|
233
|
+
const staleIds = staleMemories.map((m) => m.id);
|
|
234
|
+
await tx `
|
|
235
|
+
UPDATE memory_semantic
|
|
236
|
+
SET is_archived = true
|
|
237
|
+
WHERE id IN ${sql(staleIds)};
|
|
238
|
+
`;
|
|
239
|
+
for (const m of staleMemories) {
|
|
240
|
+
console.log(`[PHASE 3] -> Archived stale: "${m.content.substring(0, 60)}..." (tier=${m.tier}, age=${Math.round((Date.now() - new Date(m.created_at).getTime()) / 86400000)}d)`);
|
|
241
|
+
}
|
|
242
|
+
return staleMemories.length;
|
|
243
|
+
});
|
|
244
|
+
console.log(`[PHASE 3] Archived ${result} low-value memories.`);
|
|
245
|
+
return result;
|
|
246
|
+
}
|
|
247
|
+
// =============================================================================
|
|
248
|
+
// PHASE 4: LINK CANDIDATE DISCOVERY & AUTO-LINKING
|
|
249
|
+
// =============================================================================
|
|
250
|
+
async function phaseLinkDiscovery(agentId, llmUrl, llmModel) {
|
|
251
|
+
console.log(`\n[PHASE 4] Link Candidate Discovery & Auto-Linking`);
|
|
252
|
+
console.log(`─────────────────────────────────────────`);
|
|
253
|
+
console.log(`[PHASE 4] Similarity range: ${LINK_SIMILARITY_MIN}–${LINK_SIMILARITY_MAX}`);
|
|
254
|
+
const sql = (0, db_js_1.getSql)();
|
|
255
|
+
const sourceMemories = await sql.begin(async (tx) => {
|
|
256
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
257
|
+
return await tx `
|
|
258
|
+
SELECT id, content, embedding
|
|
259
|
+
FROM memory_semantic
|
|
260
|
+
WHERE agent_id = ${agentId} AND is_archived = false
|
|
261
|
+
ORDER BY created_at DESC
|
|
262
|
+
LIMIT ${LINK_SCAN_LIMIT};
|
|
263
|
+
`;
|
|
264
|
+
});
|
|
265
|
+
if (sourceMemories.length < 2) {
|
|
266
|
+
console.log(`[PHASE 4] Not enough memories for link discovery (${sourceMemories.length}).`);
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
269
|
+
console.log(`[PHASE 4] Scanning ${sourceMemories.length} memories for link candidates...`);
|
|
270
|
+
const candidatePairs = [];
|
|
271
|
+
const seenPairs = new Set();
|
|
272
|
+
await sql.begin(async (tx) => {
|
|
273
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
274
|
+
for (const source of sourceMemories) {
|
|
275
|
+
const candidates = await tx `
|
|
276
|
+
SELECT m.id, m.content, 1 - (m.embedding <=> ${source.embedding}) AS similarity
|
|
277
|
+
FROM memory_semantic m
|
|
278
|
+
WHERE m.agent_id = ${agentId}
|
|
279
|
+
AND m.is_archived = false
|
|
280
|
+
AND m.id != ${source.id}
|
|
281
|
+
AND 1 - (m.embedding <=> ${source.embedding}) BETWEEN ${LINK_SIMILARITY_MIN} AND ${LINK_SIMILARITY_MAX}
|
|
282
|
+
AND NOT EXISTS (
|
|
283
|
+
SELECT 1 FROM entity_edges e
|
|
284
|
+
WHERE e.agent_id = ${agentId}
|
|
285
|
+
AND (
|
|
286
|
+
(e.source_memory_id = ${source.id} AND e.target_memory_id = m.id)
|
|
287
|
+
OR (e.source_memory_id = m.id AND e.target_memory_id = ${source.id})
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
ORDER BY similarity DESC
|
|
291
|
+
LIMIT ${LINK_CANDIDATES_PER_MEMORY};
|
|
292
|
+
`;
|
|
293
|
+
for (const candidate of candidates) {
|
|
294
|
+
const pairKey = [source.id, candidate.id].sort().join(":");
|
|
295
|
+
if (seenPairs.has(pairKey))
|
|
296
|
+
continue;
|
|
297
|
+
seenPairs.add(pairKey);
|
|
298
|
+
candidatePairs.push({
|
|
299
|
+
source_id: source.id,
|
|
300
|
+
source_content: source.content,
|
|
301
|
+
target_id: candidate.id,
|
|
302
|
+
target_content: candidate.content,
|
|
303
|
+
similarity: candidate.similarity,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
if (candidatePairs.length === 0) {
|
|
309
|
+
console.log(`[PHASE 4] No new link candidates found.`);
|
|
310
|
+
return 0;
|
|
311
|
+
}
|
|
312
|
+
console.log(`[PHASE 4] Found ${candidatePairs.length} candidate pairs. Classifying relationships...`);
|
|
313
|
+
let linksCreated = 0;
|
|
314
|
+
for (let i = 0; i < candidatePairs.length; i += LINK_BATCH_SIZE) {
|
|
315
|
+
const batch = candidatePairs.slice(i, i + LINK_BATCH_SIZE);
|
|
316
|
+
const pairsDescription = batch
|
|
317
|
+
.map((p, idx) => `${idx + 1}. [A: ${p.source_id}] "${p.source_content}"\n [B: ${p.target_id}] "${p.target_content}" (similarity: ${(p.similarity * 100).toFixed(1)}%)`)
|
|
318
|
+
.join("\n\n");
|
|
319
|
+
const systemPrompt = `
|
|
320
|
+
You are a knowledge graph relationship classifier.
|
|
321
|
+
Given pairs of memory entries, classify the relationship between them.
|
|
322
|
+
|
|
323
|
+
Valid relationship types:
|
|
324
|
+
- "related_to" — general topical relation
|
|
325
|
+
- "elaborates" — B provides more detail about A
|
|
326
|
+
- "contradicts" — B conflicts with or corrects A
|
|
327
|
+
- "depends_on" — B depends on knowledge from A
|
|
328
|
+
- "part_of" — B is a component/subset of A
|
|
329
|
+
- "none" — no meaningful relationship worth linking
|
|
330
|
+
|
|
331
|
+
Output EXCLUSIVELY a JSON array of objects:
|
|
332
|
+
[{"source_id": "...", "target_id": "...", "relationship": "..."}]
|
|
333
|
+
|
|
334
|
+
Use "none" for pairs that don't have a meaningful relationship worth persisting.
|
|
335
|
+
Do not use markdown formatting.
|
|
336
|
+
`;
|
|
337
|
+
const jsonString = await callLLM(systemPrompt, `Classify the relationships between these memory pairs:\n\n${pairsDescription}`, llmUrl, llmModel);
|
|
338
|
+
let classifications;
|
|
339
|
+
try {
|
|
340
|
+
classifications = JSON.parse(jsonString);
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
console.error(`[PHASE 4] Failed to parse LLM response for batch ${Math.floor(i / LINK_BATCH_SIZE) + 1}. Skipping.`);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
await sql.begin(async (tx) => {
|
|
347
|
+
await tx `SELECT set_config('app.current_agent_id', ${agentId}, true)`;
|
|
348
|
+
for (const cls of classifications) {
|
|
349
|
+
if (cls.relationship === "none" || !cls.relationship)
|
|
350
|
+
continue;
|
|
351
|
+
try {
|
|
352
|
+
await tx `
|
|
353
|
+
INSERT INTO entity_edges (agent_id, source_memory_id, target_memory_id, relationship_type, weight)
|
|
354
|
+
VALUES (${agentId}, ${cls.source_id}, ${cls.target_id}, ${cls.relationship}, 1.0)
|
|
355
|
+
ON CONFLICT (source_memory_id, target_memory_id, relationship_type) DO NOTHING;
|
|
356
|
+
`;
|
|
357
|
+
linksCreated++;
|
|
358
|
+
console.log(`[PHASE 4] -> Linked: ${cls.source_id.substring(0, 8)} → ${cls.target_id.substring(0, 8)} as "${cls.relationship}"`);
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
console.error(`[PHASE 4] Failed to insert edge: ${err}`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
console.log(`[PHASE 4] Created ${linksCreated} new knowledge graph edges.`);
|
|
367
|
+
return linksCreated;
|
|
368
|
+
}
|
|
369
|
+
// =============================================================================
|
|
370
|
+
// MAIN: RUN ALL PHASES
|
|
371
|
+
// =============================================================================
|
|
372
|
+
async function runSleepCycle(opts = {}) {
|
|
373
|
+
const agentId = opts.agentId || "main";
|
|
374
|
+
const llmUrl = opts.llmUrl || db_js_1.LM_STUDIO_URL || "http://127.0.0.1:1234/v1";
|
|
375
|
+
const llmModel = opts.llmModel || "qwen3.5-9b";
|
|
376
|
+
console.log(`\n╔══════════════════════════════════════════════════════╗`);
|
|
377
|
+
console.log(`║ SLEEP CYCLE — Knowledge Graph Maintenance Agent ║`);
|
|
378
|
+
console.log(`║ Agent: ${agentId.padEnd(44)}║`);
|
|
379
|
+
console.log(`╚══════════════════════════════════════════════════════╝`);
|
|
380
|
+
await (0, memoryService_js_1.ensureAgent)(agentId);
|
|
381
|
+
const stats = {
|
|
382
|
+
factsExtracted: 0,
|
|
383
|
+
duplicatesMerged: 0,
|
|
384
|
+
staleArchived: 0,
|
|
385
|
+
linksCreated: 0,
|
|
386
|
+
};
|
|
387
|
+
try {
|
|
388
|
+
stats.factsExtracted = await phaseConsolidateEpisodic(agentId, llmUrl, llmModel);
|
|
389
|
+
stats.duplicatesMerged = await phaseDuplicateDetection(agentId);
|
|
390
|
+
stats.staleArchived = await phaseLowValueCleanup(agentId);
|
|
391
|
+
stats.linksCreated = await phaseLinkDiscovery(agentId, llmUrl, llmModel);
|
|
392
|
+
console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
|
|
393
|
+
console.log(` Sleep Cycle Complete 💤`);
|
|
394
|
+
console.log(` Facts extracted: ${stats.factsExtracted}`);
|
|
395
|
+
console.log(` Duplicates merged: ${stats.duplicatesMerged}`);
|
|
396
|
+
console.log(` Stale archived: ${stats.staleArchived}`);
|
|
397
|
+
console.log(` Links created: ${stats.linksCreated}`);
|
|
398
|
+
console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
console.error("[SLEEP CYCLE] Fatal error during maintenance:", err);
|
|
402
|
+
}
|
|
403
|
+
return stats;
|
|
404
|
+
}
|
|
405
|
+
// =============================================================================
|
|
406
|
+
// BACKGROUND SERVICE — runs on an interval while the gateway is up
|
|
407
|
+
// =============================================================================
|
|
408
|
+
let _serviceTimer = null;
|
|
409
|
+
function startService(opts = {}) {
|
|
410
|
+
const intervalMs = (opts.intervalHours || DEFAULT_INTERVAL_HOURS) * 60 * 60 * 1000;
|
|
411
|
+
const label = `${opts.intervalHours || DEFAULT_INTERVAL_HOURS}h`;
|
|
412
|
+
console.log(`[SLEEP SERVICE] Started — will run every ${label} for agent="${opts.agentId || "main"}"`);
|
|
413
|
+
// Run once immediately, then on interval
|
|
414
|
+
runSleepCycle(opts).catch((err) => console.error("[SLEEP SERVICE] Cycle failed:", err));
|
|
415
|
+
_serviceTimer = setInterval(() => {
|
|
416
|
+
console.log(`[SLEEP SERVICE] Interval tick — starting cycle`);
|
|
417
|
+
runSleepCycle(opts).catch((err) => console.error("[SLEEP SERVICE] Cycle failed:", err));
|
|
418
|
+
}, intervalMs);
|
|
419
|
+
}
|
|
420
|
+
function stopService() {
|
|
421
|
+
if (_serviceTimer) {
|
|
422
|
+
clearInterval(_serviceTimer);
|
|
423
|
+
_serviceTimer = null;
|
|
424
|
+
console.log(`[SLEEP SERVICE] Stopped`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// =============================================================================
|
|
428
|
+
// STANDALONE CLI ENTRY POINT
|
|
429
|
+
// =============================================================================
|
|
430
|
+
if (require.main === module) {
|
|
431
|
+
const args = process.argv.slice(2);
|
|
432
|
+
function getArg(name) {
|
|
433
|
+
const idx = args.indexOf(name);
|
|
434
|
+
if (idx === -1)
|
|
435
|
+
return undefined;
|
|
436
|
+
return args[idx + 1];
|
|
437
|
+
}
|
|
438
|
+
runSleepCycle({
|
|
439
|
+
agentId: getArg("--agent-id") || args.find((a) => !a.startsWith("--")),
|
|
440
|
+
llmUrl: getArg("--llm-url"),
|
|
441
|
+
llmModel: getArg("--llm-model"),
|
|
442
|
+
})
|
|
443
|
+
.then(() => {
|
|
444
|
+
(0, db_js_1.getSql)().end();
|
|
445
|
+
process.exit(0);
|
|
446
|
+
})
|
|
447
|
+
.catch(() => {
|
|
448
|
+
(0, db_js_1.getSql)().end();
|
|
449
|
+
process.exit(1);
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
//# sourceMappingURL=sleep_cycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sleep_cycle.js","sourceRoot":"","sources":["../../scripts/sleep_cycle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import postgres from "postgres";
|
|
2
|
+
import "dotenv/config";
|
|
3
|
+
export declare let LM_STUDIO_URL: string | undefined;
|
|
4
|
+
export declare let POSTCLAW_DB_URL: string | undefined;
|
|
5
|
+
export declare let EMBEDDING_MODEL: string;
|
|
6
|
+
/**
|
|
7
|
+
* Set the database connection URL. Called by the plugin register() if the user
|
|
8
|
+
* supplies `dbUrl` in the plugin config. Falls back to env var POSTCLAW_DB_URL.
|
|
9
|
+
*/
|
|
10
|
+
export declare function setDbUrl(url: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Configure the embedding provider settings. Usually called by index.ts during OpenClaw initialization.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setEmbeddingConfig(url: string, model: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Returns the shared postgres client, creating it on first use. This allows the
|
|
17
|
+
* plugin config (`dbUrl`) to be applied before the connection is opened.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getSql(): ReturnType<typeof postgres>;
|
|
20
|
+
/**
|
|
21
|
+
* Generate a vector embedding for a given text string via LM Studio.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getEmbedding(text: string): Promise<number[]>;
|
|
24
|
+
/**
|
|
25
|
+
* SHA-256 content hash for deduplication.
|
|
26
|
+
*/
|
|
27
|
+
export declare function hashContent(content: string): string;
|
|
28
|
+
//# sourceMappingURL=db.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../services/db.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,eAAe,CAAC;AAMvB,eAAO,IAAI,aAAa,oBAA4B,CAAC;AACrD,eAAO,IAAI,eAAe,oBAA8B,CAAC;AACzD,eAAO,IAAI,eAAe,QAA0E,CAAC;AAErG;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,QAEnC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAI5D;AAQD;;;GAGG;AACH,wBAAgB,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAYpD;AAMD;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkClE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.EMBEDDING_MODEL = exports.POSTCLAW_DB_URL = exports.LM_STUDIO_URL = void 0;
|
|
7
|
+
exports.setDbUrl = setDbUrl;
|
|
8
|
+
exports.setEmbeddingConfig = setEmbeddingConfig;
|
|
9
|
+
exports.getSql = getSql;
|
|
10
|
+
exports.getEmbedding = getEmbedding;
|
|
11
|
+
exports.hashContent = hashContent;
|
|
12
|
+
const postgres_1 = __importDefault(require("postgres"));
|
|
13
|
+
const node_crypto_1 = require("node:crypto");
|
|
14
|
+
require("dotenv/config");
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// CONFIG
|
|
17
|
+
// =============================================================================
|
|
18
|
+
exports.LM_STUDIO_URL = process.env.LM_STUDIO_URL;
|
|
19
|
+
exports.POSTCLAW_DB_URL = process.env.POSTCLAW_DB_URL;
|
|
20
|
+
exports.EMBEDDING_MODEL = process.env.EMBEDDING_MODEL || "text-embedding-nomic-embed-text-v2-moe";
|
|
21
|
+
/**
|
|
22
|
+
* Set the database connection URL. Called by the plugin register() if the user
|
|
23
|
+
* supplies `dbUrl` in the plugin config. Falls back to env var POSTCLAW_DB_URL.
|
|
24
|
+
*/
|
|
25
|
+
function setDbUrl(url) {
|
|
26
|
+
exports.POSTCLAW_DB_URL = url;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configure the embedding provider settings. Usually called by index.ts during OpenClaw initialization.
|
|
30
|
+
*/
|
|
31
|
+
function setEmbeddingConfig(url, model) {
|
|
32
|
+
exports.LM_STUDIO_URL = url;
|
|
33
|
+
exports.EMBEDDING_MODEL = model;
|
|
34
|
+
console.log(`[EMBED] Configured via OpenClaw -> Base: ${url} | Model: ${model}`);
|
|
35
|
+
}
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// DATABASE CLIENT — Lazily initialized
|
|
38
|
+
// =============================================================================
|
|
39
|
+
let _sql = null;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the shared postgres client, creating it on first use. This allows the
|
|
42
|
+
* plugin config (`dbUrl`) to be applied before the connection is opened.
|
|
43
|
+
*/
|
|
44
|
+
function getSql() {
|
|
45
|
+
if (_sql)
|
|
46
|
+
return _sql;
|
|
47
|
+
if (!exports.POSTCLAW_DB_URL) {
|
|
48
|
+
throw new Error("Missing database URL. Set 'dbUrl' in plugins.entries.postclaw.config or the POSTCLAW_DB_URL environment variable.");
|
|
49
|
+
}
|
|
50
|
+
_sql = (0, postgres_1.default)(exports.POSTCLAW_DB_URL);
|
|
51
|
+
console.log(`[PostClaw] Database connection established`);
|
|
52
|
+
return _sql;
|
|
53
|
+
}
|
|
54
|
+
// =============================================================================
|
|
55
|
+
// UTILITIES
|
|
56
|
+
// =============================================================================
|
|
57
|
+
/**
|
|
58
|
+
* Generate a vector embedding for a given text string via LM Studio.
|
|
59
|
+
*/
|
|
60
|
+
async function getEmbedding(text) {
|
|
61
|
+
if (!exports.LM_STUDIO_URL) {
|
|
62
|
+
throw new Error(`[EMBED] Cannot get embedding. Configuration not injected.`);
|
|
63
|
+
}
|
|
64
|
+
if (!text || typeof text !== "string" || !text.trim()) {
|
|
65
|
+
throw new Error(`[EMBED] Refusing to embed empty/undefined text (received: ${JSON.stringify(text)})`);
|
|
66
|
+
}
|
|
67
|
+
const body = JSON.stringify({ input: text, model: exports.EMBEDDING_MODEL });
|
|
68
|
+
console.log(`[EMBED] Request body preview: ${body.substring(0, 200)}`);
|
|
69
|
+
// Strip any trailing /v1 or /v1/ from the base URL to avoid doubling
|
|
70
|
+
const baseUrl = exports.LM_STUDIO_URL.replace(/\/v1\/?$/, "");
|
|
71
|
+
const res = await fetch(`${baseUrl}/v1/embeddings`, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers: { "Content-Type": "application/json" },
|
|
74
|
+
body,
|
|
75
|
+
});
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
throw new Error(`Embedding API error: ${res.status} ${res.statusText}`);
|
|
78
|
+
}
|
|
79
|
+
const data = await res.json();
|
|
80
|
+
if (!data?.data?.[0]?.embedding) {
|
|
81
|
+
throw new Error(`[EMBED] Unexpected API response (missing data.data[0].embedding). URL: ${baseUrl}/v1/embeddings — Response: ${JSON.stringify(data).substring(0, 300)}`);
|
|
82
|
+
}
|
|
83
|
+
const embedding = data.data[0].embedding;
|
|
84
|
+
console.log(`[EMBED] Generated ${embedding.length}-dim vector for: "${text.substring(0, 50)}..."`);
|
|
85
|
+
return embedding;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* SHA-256 content hash for deduplication.
|
|
89
|
+
*/
|
|
90
|
+
function hashContent(content) {
|
|
91
|
+
return (0, node_crypto_1.createHash)("sha256").update(content).digest("hex");
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../services/db.ts"],"names":[],"mappings":";;;;;;AAgBA,4BAEC;AAKD,gDAIC;AAYD,wBAYC;AASD,oCAkCC;AAKD,kCAEC;AArGD,wDAAgC;AAChC,6CAAyC;AACzC,yBAAuB;AAEvB,gFAAgF;AAChF,SAAS;AACT,gFAAgF;AAErE,QAAA,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AAC1C,QAAA,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;AAC9C,QAAA,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wCAAwC,CAAC;AAErG;;;GAGG;AACH,SAAgB,QAAQ,CAAC,GAAW;IAClC,uBAAe,GAAG,GAAG,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,GAAW,EAAE,KAAa;IAC3D,qBAAa,GAAG,GAAG,CAAC;IACpB,uBAAe,GAAG,KAAK,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,4CAA4C,GAAG,aAAa,KAAK,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,gFAAgF;AAChF,uCAAuC;AACvC,gFAAgF;AAEhF,IAAI,IAAI,GAAuC,IAAI,CAAC;AAEpD;;;GAGG;AACH,SAAgB,MAAM;IACpB,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC,uBAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,mHAAmH,CACpH,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,IAAA,kBAAQ,EAAC,uBAAe,CAAC,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF;;GAEG;AACI,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,IAAI,CAAC,qBAAa,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;IAC/E,CAAC;IAED,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,6DAA6D,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxG,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,uBAAe,EAAE,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAEvE,qEAAqE;IACrE,MAAM,OAAO,GAAG,qBAAc,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,gBAAgB,EAAE;QAClD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI;KACL,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,IAAI,GAAQ,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,0EAA0E,OAAO,8BAA8B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3K,CAAC;IAED,MAAM,SAAS,GAAa,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEnD,OAAO,CAAC,GAAG,CAAC,qBAAqB,SAAS,CAAC,MAAM,qBAAqB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IACnG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,WAAW,CAAC,OAAe;IACzC,OAAO,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC"}
|