@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.
Files changed (46) hide show
  1. package/.env.example +4 -0
  2. package/LICENSE +15 -0
  3. package/README.md +731 -0
  4. package/dist/index.d.ts +36 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +506 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/schemas/validation.d.ts +81 -0
  9. package/dist/schemas/validation.d.ts.map +1 -0
  10. package/dist/schemas/validation.js +27 -0
  11. package/dist/schemas/validation.js.map +1 -0
  12. package/dist/scripts/bootstrap_persona.d.ts +20 -0
  13. package/dist/scripts/bootstrap_persona.d.ts.map +1 -0
  14. package/dist/scripts/bootstrap_persona.js +150 -0
  15. package/dist/scripts/bootstrap_persona.js.map +1 -0
  16. package/dist/scripts/bootstrap_tools.d.ts +2 -0
  17. package/dist/scripts/bootstrap_tools.d.ts.map +1 -0
  18. package/dist/scripts/bootstrap_tools.js +67 -0
  19. package/dist/scripts/bootstrap_tools.js.map +1 -0
  20. package/dist/scripts/setup-db.d.ts +28 -0
  21. package/dist/scripts/setup-db.d.ts.map +1 -0
  22. package/dist/scripts/setup-db.js +539 -0
  23. package/dist/scripts/setup-db.js.map +1 -0
  24. package/dist/scripts/sleep_cycle.d.ts +32 -0
  25. package/dist/scripts/sleep_cycle.d.ts.map +1 -0
  26. package/dist/scripts/sleep_cycle.js +452 -0
  27. package/dist/scripts/sleep_cycle.js.map +1 -0
  28. package/dist/services/db.d.ts +28 -0
  29. package/dist/services/db.d.ts.map +1 -0
  30. package/dist/services/db.js +93 -0
  31. package/dist/services/db.js.map +1 -0
  32. package/dist/services/memoryService.d.ts +75 -0
  33. package/dist/services/memoryService.d.ts.map +1 -0
  34. package/dist/services/memoryService.js +391 -0
  35. package/dist/services/memoryService.js.map +1 -0
  36. package/dist/test-db.d.ts +8 -0
  37. package/dist/test-db.d.ts.map +1 -0
  38. package/dist/test-db.js +94 -0
  39. package/dist/test-db.js.map +1 -0
  40. package/dist/test-memory.d.ts +2 -0
  41. package/dist/test-memory.d.ts.map +1 -0
  42. package/dist/test-memory.js +79 -0
  43. package/dist/test-memory.js.map +1 -0
  44. package/openclaw.plugin.json +37 -0
  45. package/package.json +49 -0
  46. 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":"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"}