supaclaw 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/README.md ADDED
@@ -0,0 +1,871 @@
1
+ # 🧠 Supaclaw
2
+
3
+ **Persistent memory for AI agents using Supabase.**
4
+
5
+ Stop losing context. Stop re-reading massive markdown files. Give your agent a real memory.
6
+
7
+ [![npm version](https://badge.fury.io/js/supaclaw.svg)](https://www.npmjs.com/package/supaclaw)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ## The Problem
11
+
12
+ AI agents using file-based memory (MEMORY.md, daily logs) face:
13
+ - **Context window bloat** - Files grow unbounded, eating your token budget
14
+ - **Forgetting** - Context resets wipe session memory
15
+ - **No search** - Linear scan through text to find relevant info
16
+ - **Unstructured** - Can't query "what did we discuss about X?"
17
+
18
+ ## The Solution
19
+
20
+ Supaclaw uses **Supabase (Postgres)** to give your agent:
21
+ - ✅ **Session tracking** - Every conversation logged with metadata
22
+ - ✅ **Semantic search** - Find relevant memories via vector similarity (pgvector)
23
+ - ✅ **Smart context** - Only load what's relevant, not everything
24
+ - ✅ **Context window management** - Token budgeting, smart selection, lost-in-middle mitigation
25
+ - ✅ **Entity relationships** - Knowledge graph with multi-hop traversal, confidence scoring
26
+ - ✅ **Multi-agent** - Share memories across agents
27
+ - ✅ **Structured data** - SQL queries, relationships, types
28
+
29
+ ## Quick Start
30
+
31
+ ```bash
32
+ npm install supaclaw
33
+ ```
34
+
35
+ ```typescript
36
+ import { OpenClawMemory } from 'supaclaw';
37
+
38
+ const memory = new OpenClawMemory({
39
+ supabaseUrl: process.env.SUPABASE_URL,
40
+ supabaseKey: process.env.SUPABASE_KEY,
41
+ agentId: 'my-agent',
42
+ // Optional: Enable semantic search with OpenAI embeddings
43
+ embeddingProvider: 'openai',
44
+ openaiApiKey: process.env.OPENAI_API_KEY
45
+ });
46
+
47
+ // Initialize tables (first run only)
48
+ await memory.initialize();
49
+
50
+ // Start a conversation session
51
+ const session = await memory.startSession({
52
+ userId: 'user-123',
53
+ channel: 'telegram'
54
+ });
55
+
56
+ // Log messages
57
+ await memory.addMessage(session.id, {
58
+ role: 'user',
59
+ content: 'Remember that I prefer TypeScript over JavaScript'
60
+ });
61
+
62
+ // Create a persistent memory
63
+ await memory.remember({
64
+ content: 'User prefers TypeScript over JavaScript',
65
+ category: 'preference',
66
+ importance: 0.9
67
+ });
68
+
69
+ // Later: recall relevant memories (semantic search if embeddings enabled)
70
+ const memories = await memory.recall('programming language preferences', {
71
+ minSimilarity: 0.7, // Cosine similarity threshold
72
+ limit: 10
73
+ });
74
+ // Returns: [{ content: 'User prefers TypeScript...', importance: 0.9, similarity: 0.85, ... }]
75
+
76
+ // Or use hybrid search (combines semantic + keyword matching)
77
+ const hybrid = await memory.hybridRecall('coding tips', {
78
+ vectorWeight: 0.7, // Weight for semantic similarity
79
+ keywordWeight: 0.3, // Weight for keyword matching
80
+ limit: 10
81
+ });
82
+
83
+ // Find memories similar to an existing one
84
+ const similar = await memory.findSimilarMemories(memoryId, {
85
+ minSimilarity: 0.8,
86
+ limit: 5
87
+ });
88
+
89
+ // End session with AI-generated summary
90
+ await memory.endSession(session.id, { autoSummarize: true });
91
+
92
+ // Resume interrupted session
93
+ const { session, messages, context } = await memory.resumeSession(sessionId);
94
+
95
+ // Extract entities from conversation
96
+ const entities = await memory.extractEntities('I love using Claude for coding');
97
+ // Returns: [{ entity_type: 'product', name: 'Claude', description: '...' }]
98
+
99
+ // Extract entities AND relationships in one call
100
+ const { entities, relationships } = await memory.extractEntitiesWithRelationships(
101
+ 'Alice works at TechCorp in San Francisco'
102
+ );
103
+ // Returns entities: Han (person), TechCorp (organization), San Francisco (place)
104
+ // Returns relationships: Han → works_at → TechCorp, TechCorp → located_in → San Francisco
105
+
106
+ // Find related entities through graph traversal (multi-hop)
107
+ const related = await memory.findRelatedEntities(hanId, { maxDepth: 2 });
108
+ // Returns entities connected within 2 hops with relationship paths and confidence scores
109
+
110
+ // Create tasks with hierarchy
111
+ const project = await memory.createTask({ title: 'Build feature X' });
112
+ await memory.createTask({
113
+ title: 'Design UI',
114
+ parentTaskId: project.id
115
+ });
116
+
117
+ // Get upcoming tasks (due in next 24h)
118
+ const upcoming = await memory.getUpcomingTasks({ hoursAhead: 24 });
119
+
120
+ // Record learnings for future context
121
+ await memory.learn({
122
+ category: 'error',
123
+ trigger: 'Database migration failed',
124
+ lesson: 'Always backup before schema changes',
125
+ severity: 'critical'
126
+ });
127
+
128
+ // Search learnings when facing similar issues
129
+ const relevantLearnings = await memory.searchLearnings('database');
130
+ ```
131
+
132
+ ## Database Schema
133
+
134
+ ### Sessions
135
+ ```sql
136
+ sessions (id, agent_id, user_id, channel, started_at, ended_at, summary, metadata)
137
+ ```
138
+
139
+ ### Messages
140
+ ```sql
141
+ messages (id, session_id, role, content, created_at, token_count, metadata)
142
+ ```
143
+
144
+ ### Memories
145
+ ```sql
146
+ memories (id, agent_id, user_id, category, content, importance, embedding, expires_at, ...)
147
+ ```
148
+
149
+ ### Entities
150
+ ```sql
151
+ entities (id, agent_id, entity_type, name, aliases, properties, embedding, ...)
152
+ ```
153
+
154
+ ### Entity Relationships
155
+ ```sql
156
+ entity_relationships (id, agent_id, source_entity_id, target_entity_id, relationship_type,
157
+ confidence, mention_count, properties, ...)
158
+ ```
159
+
160
+ ### Tasks
161
+ ```sql
162
+ tasks (id, agent_id, title, status, priority, due_at, ...)
163
+ ```
164
+
165
+ ### Learnings
166
+ ```sql
167
+ learnings (id, agent_id, category, trigger, lesson, action, severity, ...)
168
+ ```
169
+
170
+ See [SCHEMA.md](./SCHEMA.md) for full details.
171
+
172
+ ## Search Modes
173
+
174
+ Supaclaw supports three search strategies:
175
+
176
+ ### 📝 Keyword Search (Default)
177
+ Traditional text matching - fast, no API keys needed.
178
+
179
+ ```typescript
180
+ const results = await memory.recall('TypeScript', { limit: 10 });
181
+ ```
182
+
183
+ ### 🧠 Semantic Search
184
+ Uses OpenAI embeddings for meaning-based search. Understands that "coding tips" and "programming best practices" are related.
185
+
186
+ ```typescript
187
+ const results = await memory.recall('machine learning', {
188
+ minSimilarity: 0.75, // Cosine similarity threshold (0-1)
189
+ limit: 10
190
+ });
191
+ ```
192
+
193
+ **Requirements:**
194
+ - `embeddingProvider: 'openai'` in config
195
+ - `OPENAI_API_KEY` environment variable
196
+ - Run migration `002_vector_search.sql`
197
+
198
+ ### ⚡ Hybrid Search (Best Results)
199
+ Combines semantic understanding with keyword matching.
200
+
201
+ ```typescript
202
+ const results = await memory.hybridRecall('AI agents', {
203
+ vectorWeight: 0.7, // 70% semantic similarity
204
+ keywordWeight: 0.3, // 30% keyword matching
205
+ limit: 10
206
+ });
207
+ ```
208
+
209
+ **When to use each:**
210
+ - **Keyword** - Fast lookups, exact term matching
211
+ - **Semantic** - Conceptual search, understanding context
212
+ - **Hybrid** - Best overall results, balances both strategies
213
+
214
+ ## 🎯 Context Window Management
215
+
216
+ Advanced token budgeting and smart context selection to optimize LLM performance.
217
+
218
+ ### Smart Context Generation
219
+
220
+ ```typescript
221
+ // Simple: Get optimized context for a query
222
+ const context = await memory.getSmartContext('What did we discuss about the project?', {
223
+ sessionId: 'current-session',
224
+ model: 'claude-3.5-sonnet' // Auto-configures for 200k context
225
+ });
226
+
227
+ // Advanced: Full control over budget and selection
228
+ const result = await memory.buildOptimizedContext({
229
+ query: 'Project updates',
230
+ sessionId: 'session-123',
231
+ model: 'claude-3.5-sonnet',
232
+ useLostInMiddleFix: true, // Place important items at edges
233
+ importanceWeight: 0.8, // 80% importance, 20% recency
234
+ recencyWeight: 0.2
235
+ });
236
+
237
+ console.log('Context:', result.formatted);
238
+ console.log('Stats:', result.stats);
239
+ ```
240
+
241
+ ### Custom Budget Allocation
242
+
243
+ ```typescript
244
+ import { createContextBudget } from 'supaclaw';
245
+
246
+ const budget = createContextBudget({
247
+ modelContextSize: 200000, // 200k tokens for Claude
248
+ recentMessagesPct: 0.5, // 50% for messages
249
+ memoriesPct: 0.3, // 30% for memories
250
+ learningsPct: 0.15, // 15% for learnings
251
+ entitiesPct: 0.05 // 5% for entities
252
+ });
253
+
254
+ const result = await memory.buildOptimizedContext({
255
+ query: 'Tell me everything',
256
+ customBudget: budget
257
+ });
258
+ ```
259
+
260
+ ### Adaptive Budgeting
261
+
262
+ Automatically adjusts allocation based on available content:
263
+
264
+ ```typescript
265
+ import { createAdaptiveBudget } from 'supaclaw';
266
+
267
+ const budget = createAdaptiveBudget({
268
+ messageCount: 100, // Lots of messages
269
+ memoryCount: 20, // Few memories
270
+ learningCount: 10,
271
+ entityCount: 5
272
+ });
273
+ // Result: More budget allocated to messages
274
+ ```
275
+
276
+ ### Lost-in-Middle Mitigation
277
+
278
+ Research shows LLMs pay less attention to content in the middle of long contexts. OpenClaw automatically places high-importance items at the beginning and end:
279
+
280
+ ```typescript
281
+ const result = await memory.buildOptimizedContext({
282
+ query: 'Important details',
283
+ useLostInMiddleFix: true // ✓ High-importance at edges
284
+ });
285
+ ```
286
+
287
+ See [CONTEXT_WINDOW_GUIDE.md](./CONTEXT_WINDOW_GUIDE.md) for detailed examples and best practices.
288
+
289
+ ## CLI Usage
290
+
291
+ ```bash
292
+ # Initialize config
293
+ npx supaclaw init
294
+
295
+ # Run migrations
296
+ npx supaclaw migrate
297
+
298
+ # Test connection
299
+ npx supaclaw test
300
+
301
+ # Check database status
302
+ npx supaclaw status
303
+
304
+ # Search memories (keyword mode)
305
+ npx supaclaw search "TypeScript"
306
+
307
+ # Semantic search (requires OPENAI_API_KEY)
308
+ npx supaclaw search "coding best practices" --mode semantic
309
+
310
+ # Hybrid search
311
+ npx supaclaw search "AI patterns" --mode hybrid --limit 15
312
+
313
+ # List sessions
314
+ npx supaclaw sessions --limit 20 --active
315
+
316
+ # Export memories
317
+ npx supaclaw export memories.md
318
+
319
+ # Import memories
320
+ npx supaclaw import MEMORY.md
321
+
322
+ # Import from Clawdbot workspace
323
+ npx supaclaw import-memory-md ~/clawd/MEMORY.md
324
+ npx supaclaw import-daily-logs ~/clawd/memory
325
+ npx supaclaw import-todo-md ~/clawd/TODO.md
326
+ npx supaclaw import-learnings-md ~/clawd/LEARNINGS.md
327
+
328
+ # Import everything at once
329
+ npx supaclaw import-all ~/clawd --user-id han
330
+ ```
331
+
332
+ ## 🤖 Clawdbot Integration
333
+
334
+ Supaclaw provides seamless integration with [Clawdbot](https://github.com/clawdbot/clawdbot) to replace file-based memory systems.
335
+
336
+ ### Installation as Clawdbot Skill
337
+
338
+ ```bash
339
+ # Install via clawdhub
340
+ clawdhub install supaclaw
341
+
342
+ # Or install globally via npm
343
+ npm install -g supaclaw
344
+ ```
345
+
346
+ ### Quick Setup
347
+
348
+ ```typescript
349
+ import { createClawdbotIntegration } from 'supaclaw';
350
+
351
+ const integration = createClawdbotIntegration({
352
+ supabaseUrl: process.env.SUPABASE_URL!,
353
+ supabaseKey: process.env.SUPABASE_KEY!,
354
+ agentId: 'hans-assistant',
355
+ userId: 'han',
356
+ embeddingProvider: 'openai',
357
+ openaiApiKey: process.env.OPENAI_API_KEY,
358
+ autoLog: true, // Auto-log all messages
359
+ sessionTimeout: 30 * 60 * 1000 // 30 min inactivity
360
+ });
361
+
362
+ await integration.initialize();
363
+ ```
364
+
365
+ ### Auto-Logging Messages
366
+
367
+ ```typescript
368
+ // User message
369
+ await integration.logUserMessage(chatId, 'What is TypeScript?', {
370
+ channel: 'telegram',
371
+ messageId: msg.id
372
+ });
373
+
374
+ // Assistant response
375
+ await integration.logAssistantMessage(chatId, 'TypeScript is...', {
376
+ model: 'claude-sonnet-4-5'
377
+ });
378
+ ```
379
+
380
+ ### Replacing memory_search Tool
381
+
382
+ **Before (file-based):**
383
+ ```typescript
384
+ function memory_search(query: string) {
385
+ const content = fs.readFileSync('MEMORY.md', 'utf-8');
386
+ return content.split('\n').filter(line =>
387
+ line.toLowerCase().includes(query.toLowerCase())
388
+ );
389
+ }
390
+ ```
391
+
392
+ **After (semantic search):**
393
+ ```typescript
394
+ async function memory_search(query: string) {
395
+ return await integration.memorySearch(query, {
396
+ userId: 'han',
397
+ limit: 5,
398
+ minImportance: 0.5
399
+ });
400
+ }
401
+ ```
402
+
403
+ **Benefits:**
404
+ - 🎯 Semantic understanding (finds "code style" when you search "programming preferences")
405
+ - 📉 95% token reduction (5 memories vs entire file)
406
+ - ⚡ Faster (database query vs file I/O)
407
+ - 🎚️ Importance filtering (only relevant memories)
408
+
409
+ ### Auto-Injecting Context into System Prompts
410
+
411
+ ```typescript
412
+ async function buildSystemPrompt(userQuery: string) {
413
+ // Get relevant memories, learnings, and recent messages
414
+ const context = await integration.buildContext(userQuery, {
415
+ includeMemories: true,
416
+ includeLearnings: true,
417
+ includeRecentMessages: true,
418
+ chatId: 'telegram-123',
419
+ maxMemories: 5,
420
+ maxLearnings: 3
421
+ });
422
+
423
+ return BASE_SYSTEM_PROMPT + '\n\n' + context;
424
+ }
425
+ ```
426
+
427
+ **Generated Context:**
428
+ ```
429
+ ## Relevant Context
430
+
431
+ - [preferences] User prefers TypeScript over JavaScript
432
+ - [projects] Working on stock trading challenge
433
+ - [context] User is actively trading TSLA
434
+
435
+ ## Past Learnings
436
+
437
+ - [correction] User prefers Rust for performance-critical code
438
+ Action: Suggest Rust for system-level tasks
439
+
440
+ ## Recent Conversation
441
+
442
+ - user: What's the stock price of TSLA?
443
+ - assistant: Tesla is currently trading at $245.
444
+ ```
445
+
446
+ ### Session Lifecycle Hooks
447
+
448
+ ```typescript
449
+ // Session auto-created on first message
450
+ const sessionId = await integration.getOrCreateSession('telegram-123');
451
+
452
+ // End session with auto-summary
453
+ await integration.endSession('telegram-123', {
454
+ autoSummarize: true,
455
+ extractMemories: true
456
+ });
457
+
458
+ // Heartbeat check (call every 30 min)
459
+ const { upcomingTasks, inactiveSessions } = await integration.heartbeat();
460
+
461
+ // Send task reminders
462
+ for (const task of upcomingTasks) {
463
+ const reminder = integration.getMemory().formatTaskReminder(task, task.timeUntilDue);
464
+ await sendNotification(reminder);
465
+ }
466
+ ```
467
+
468
+ ### Token & Cost Savings
469
+
470
+ **Before (MEMORY.md):**
471
+ - File size: 50 KB
472
+ - Tokens per turn: ~12,500
473
+ - Cost per 1M turns: ~$37.50
474
+
475
+ **After (Supaclaw):**
476
+ - Memories retrieved: 5
477
+ - Tokens per turn: ~500
478
+ - Cost per 1M turns: ~$1.50
479
+ - **💰 Savings: 96% reduction, $36/M turns**
480
+
481
+ ### Complete Integration Example
482
+
483
+ See [`skill/example-integration.ts`](skill/example-integration.ts) for a full working example showing:
484
+ - Message handler with auto-logging
485
+ - Tool replacement (memory_search, memory_get)
486
+ - Context injection
487
+ - Session lifecycle
488
+ - Heartbeat monitoring
489
+
490
+ ### Migrating from Clawdbot Memory Files
491
+
492
+ If you're using traditional Clawdbot memory files, Supaclaw can import them:
493
+
494
+ **Supported formats:**
495
+ - `MEMORY.md` → memories table (with importance and category tags)
496
+ - `memory/*.md` → sessions + messages (daily logs)
497
+ - `TODO.md` → tasks table (with status and due dates)
498
+ - `LEARNINGS.md` → learnings table (with triggers and lessons)
499
+
500
+ **Import examples:**
501
+
502
+ ```bash
503
+ # Import MEMORY.md
504
+ npx supaclaw import-memory-md ~/clawd/MEMORY.md
505
+
506
+ # Import daily logs from memory/
507
+ npx supaclaw import-daily-logs ~/clawd/memory --user-id han
508
+
509
+ # Import TODO.md
510
+ npx supaclaw import-todo-md ~/clawd/TODO.md
511
+
512
+ # Import LEARNINGS.md
513
+ npx supaclaw import-learnings-md ~/clawd/LEARNINGS.md
514
+
515
+ # Import everything at once
516
+ npx supaclaw import-all ~/clawd --user-id han
517
+ ```
518
+
519
+ **What gets imported:**
520
+ - MEMORY.md: Parses sections (##) as categories, list items and paragraphs as memories
521
+ - Daily logs: Extracts sessions and User/Assistant message exchanges
522
+ - TODO.md: Imports tasks with status (pending/completed/cancelled), priority, and due dates
523
+ - LEARNINGS.md: Imports learnings with category, trigger, lesson, and importance
524
+
525
+ **Tag support:**
526
+ - `[importance: 0.9]` - Set memory importance (0.0-1.0)
527
+ - `[2024-01-28]` - Set creation date
528
+ - `[due: 2024-02-15]` - Set task due date
529
+
530
+ ```
531
+
532
+ ## Setup Supabase
533
+
534
+ 1. Create a [Supabase](https://supabase.com) project
535
+ 2. Enable the `vector` extension:
536
+ ```sql
537
+ CREATE EXTENSION IF NOT EXISTS vector;
538
+ ```
539
+ 3. Run the migrations:
540
+ ```bash
541
+ npx supaclaw migrate
542
+ ```
543
+ 4. Set environment variables:
544
+ ```bash
545
+ SUPABASE_URL=https://your-project.supabase.co
546
+ SUPABASE_KEY=your-anon-key
547
+ ```
548
+
549
+ ## API Reference
550
+
551
+ ### `new OpenClawMemory(config)`
552
+ Create a memory instance.
553
+
554
+ **Config options:**
555
+ - `supabaseUrl` - Supabase project URL
556
+ - `supabaseKey` - Supabase anon or service key
557
+ - `agentId` - Unique identifier for this agent
558
+ - `embeddingProvider` - Optional: 'openai', 'voyage', or 'none'
559
+ - `openaiApiKey` - Required if using OpenAI embeddings
560
+ - `embeddingModel` - Optional: OpenAI model name (default: 'text-embedding-3-small')
561
+
562
+ ### `memory.initialize()`
563
+ Create database tables if they don't exist.
564
+
565
+ ### `memory.startSession(opts)`
566
+ Start a new conversation session.
567
+
568
+ ### `memory.addMessage(sessionId, message)`
569
+ Log a message to a session.
570
+
571
+ ### `memory.endSession(sessionId, opts?)`
572
+ End a session, optionally with a summary.
573
+
574
+ **Options:**
575
+ - `summary` - Manual summary text
576
+ - `autoSummarize` - Auto-generate summary using AI (requires OpenAI)
577
+
578
+ ### `memory.generateSessionSummary(sessionId)`
579
+ Generate an AI summary of a session (2-3 sentences).
580
+
581
+ ### `memory.resumeSession(sessionId)`
582
+ Resume an interrupted session with context.
583
+
584
+ **Returns:** `{ session, messages, context }`
585
+
586
+ ### `memory.searchSessions(opts?)`
587
+ Search sessions by date range and metadata.
588
+
589
+ **Options:**
590
+ - `userId`, `channel`, `startDate`, `endDate`
591
+ - `limit`, `offset`
592
+
593
+ ### `memory.exportSessionToMarkdown(sessionId)`
594
+ Export a session to markdown format.
595
+
596
+ ### `memory.importSessionFromMarkdown(markdown, opts?)`
597
+ Import a session from markdown.
598
+
599
+ ### `memory.extractMemoriesFromSession(sessionId, opts?)`
600
+ Extract key memories from a session using AI.
601
+
602
+ **Options:**
603
+ - `minImportance` - Minimum importance threshold (default: 0.5)
604
+ - `autoExtract` - Use AI to extract (requires OpenAI)
605
+
606
+ ### `memory.countSessionTokens(sessionId)`
607
+ Count total tokens used in a session.
608
+
609
+ **Returns:** `{ totalTokens, messageCount, averageTokensPerMessage }`
610
+
611
+ ### `memory.remember(memory)`
612
+ Store a long-term memory. Automatically generates embeddings if provider configured.
613
+
614
+ ### `memory.recall(query, opts?)`
615
+ Search for relevant memories using semantic similarity (if embeddings enabled) or keyword matching.
616
+
617
+ **Options:**
618
+ - `userId` - Filter by user
619
+ - `category` - Filter by category
620
+ - `limit` - Maximum results (default: 10)
621
+ - `minImportance` - Minimum importance score
622
+ - `minSimilarity` - Minimum cosine similarity (0-1, default: 0.7)
623
+
624
+ ### `memory.hybridRecall(query, opts?)`
625
+ Hybrid search combining vector similarity and keyword matching.
626
+
627
+ **Options:**
628
+ - All options from `recall()` plus:
629
+ - `vectorWeight` - Weight for semantic similarity (default: 0.7)
630
+ - `keywordWeight` - Weight for keyword matching (default: 0.3)
631
+
632
+ ### `memory.findSimilarMemories(memoryId, opts?)`
633
+ Find memories similar to an existing memory.
634
+
635
+ **Options:**
636
+ - `minSimilarity` - Minimum similarity threshold (default: 0.8)
637
+ - `limit` - Maximum results (default: 5)
638
+
639
+ ### `memory.forget(memoryId)`
640
+ Delete a memory.
641
+
642
+ ### `memory.getContext(query, opts?)`
643
+ Get relevant context for the current query (memories + recent messages).
644
+
645
+ ### `memory.createTask(task)`
646
+ Create a task with optional hierarchy.
647
+
648
+ **Options:** `title`, `description`, `priority`, `dueAt`, `parentTaskId`
649
+
650
+ ### `memory.updateTask(taskId, updates)`
651
+ Update task properties.
652
+
653
+ ### `memory.deleteTask(taskId)`
654
+ Delete a task.
655
+
656
+ ### `memory.getTasks(opts?)`
657
+ Get tasks with filters.
658
+
659
+ **Options:** `status`, `userId`, `limit`
660
+
661
+ ### `memory.getSubtasks(parentTaskId)`
662
+ Get all subtasks of a parent task.
663
+
664
+ ### `memory.getTaskWithSubtasks(taskId)`
665
+ Get a task with all its subtasks (hierarchical view).
666
+
667
+ ### `memory.getUpcomingTasks(opts?)`
668
+ Get tasks due soon (default: next 24 hours).
669
+
670
+ ### `memory.learn(learning)`
671
+ Record a learning for future reference.
672
+
673
+ **Options:** `category`, `trigger`, `lesson`, `action`, `severity`
674
+
675
+ ### `memory.getLearnings(opts?)`
676
+ Get recorded learnings.
677
+
678
+ **Options:** `category`, `severity`, `limit`
679
+
680
+ ### `memory.searchLearnings(query, opts?)`
681
+ Search learnings by topic.
682
+
683
+ ### `memory.applyLearning(learningId)`
684
+ Mark a learning as applied (increments usage count).
685
+
686
+ ### `memory.extractEntities(text, opts?)`
687
+ Extract named entities from text using AI.
688
+
689
+ **Returns:** Array of entities (person, place, organization, product, concept)
690
+
691
+ ### `memory.createEntity(entity)`
692
+ Manually create an entity.
693
+
694
+ ### `memory.updateEntity(entityId, updates)`
695
+ Update an entity (increments mention count).
696
+
697
+ ### `memory.findEntity(nameOrAlias)`
698
+ Find an entity by name or alias (case-insensitive).
699
+
700
+ ### `memory.searchEntities(opts?)`
701
+ Search entities with filters.
702
+
703
+ **Options:** `query`, `entityType`, `limit`
704
+
705
+ ### `memory.mergeEntities(primaryId, duplicateId)`
706
+ Merge duplicate entities (deduplication).
707
+
708
+ ### `memory.createEntityRelationship(rel)`
709
+ Create or update a relationship between entities.
710
+
711
+ **Parameters:**
712
+ - `sourceEntityId` - Source entity UUID
713
+ - `targetEntityId` - Target entity UUID
714
+ - `relationshipType` - Type: `works_at`, `knows`, `created`, `located_in`, etc.
715
+ - `properties` - Optional additional context
716
+ - `confidence` - Confidence score 0-1 (default: 0.5)
717
+ - `sessionId` - Optional source session
718
+
719
+ **Returns:** EntityRelationship
720
+
721
+ ### `memory.getEntityRelationships(entityId, opts?)`
722
+ Get relationships for an entity.
723
+
724
+ **Options:**
725
+ - `direction` - `'outgoing'` | `'incoming'` | `'both'` (default: `'both'`)
726
+ - `relationshipType` - Filter by type
727
+ - `minConfidence` - Minimum confidence threshold (default: 0.3)
728
+ - `limit` - Maximum results (default: 50)
729
+
730
+ **Returns:** Array of `{ relationship, relatedEntity, direction }`
731
+
732
+ ### `memory.findRelatedEntities(entityId, opts?)`
733
+ Find entities connected through multi-hop relationships (graph traversal).
734
+
735
+ **Options:**
736
+ - `maxDepth` - Maximum hops (default: 2)
737
+ - `minConfidence` - Minimum confidence threshold (default: 0.5)
738
+
739
+ **Returns:** Array of `{ entityId, entityName, entityType, relationshipPath, totalConfidence, depth }`
740
+
741
+ ### `memory.getEntityNetworkStats()`
742
+ Get entity network statistics.
743
+
744
+ **Returns:** `{ totalEntities, totalRelationships, avgConnectionsPerEntity, mostConnectedEntity }`
745
+
746
+ ### `memory.extractEntitiesWithRelationships(text, opts?)`
747
+ Extract entities AND relationships from text using AI (one call).
748
+
749
+ **Returns:** `{ entities: Entity[], relationships: EntityRelationship[] }`
750
+
751
+ ### `memory.searchRelationships(opts?)`
752
+ Search relationships with filters.
753
+
754
+ **Options:** `relationshipType`, `minConfidence`, `limit`
755
+
756
+ ### `memory.deleteEntityRelationship(relationshipId)`
757
+ Delete a relationship.
758
+
759
+ ### `memory.decayMemoryImportance(opts?)`
760
+ Apply importance decay to old memories (lifecycle management).
761
+
762
+ **Options:**
763
+ - `userId` - Filter by user
764
+ - `decayRate` - Decay rate 0-1 (default: 0.1)
765
+ - `minImportance` - Minimum importance threshold (default: 0.1)
766
+ - `olderThanDays` - Only decay memories older than X days (default: 7)
767
+
768
+ **Returns:** `{ updated: number, avgDecay: number }`
769
+
770
+ ### `memory.consolidateMemories(opts?)`
771
+ Merge similar/duplicate memories to reduce clutter.
772
+
773
+ **Options:**
774
+ - `userId` - Filter by user
775
+ - `similarityThreshold` - Similarity threshold 0-1 (default: 0.9)
776
+ - `category` - Filter by category
777
+ - `limit` - Max pairs to check (default: 100)
778
+
779
+ **Returns:** `{ merged: number, kept: number }`
780
+
781
+ ### `memory.versionMemory(memoryId)`
782
+ Create a version snapshot of a memory.
783
+
784
+ **Returns:** `{ memory, versionId }`
785
+
786
+ ### `memory.getMemoryVersions(memoryId)`
787
+ Get version history for a memory.
788
+
789
+ **Returns:** Array of `{ version, timestamp, content, importance }`
790
+
791
+ ### `memory.tagMemory(memoryId, tags)`
792
+ Add tags to a memory for organization.
793
+
794
+ ### `memory.untagMemory(memoryId, tags)`
795
+ Remove tags from a memory.
796
+
797
+ ### `memory.searchMemoriesByTags(tags, opts?)`
798
+ Search memories by tags.
799
+
800
+ **Options:**
801
+ - `matchAll` - If true, must match ALL tags; if false, match ANY (default: false)
802
+ - `limit` - Maximum results (default: 50)
803
+
804
+ ### `memory.cleanupOldSessions(opts?)`
805
+ Archive or delete old sessions (maintenance).
806
+
807
+ **Options:**
808
+ - `olderThanDays` - Archive sessions older than X days (default: 90)
809
+ - `action` - 'archive' or 'delete' (default: 'archive')
810
+ - `keepSummaries` - Keep sessions with summaries (default: true)
811
+ - `userId` - Filter by user
812
+
813
+ **Returns:** `{ archived?: number, deleted?: number }`
814
+
815
+ ### `memory.getCleanupStats()`
816
+ Get cleanup statistics for monitoring.
817
+
818
+ **Returns:** `{ totalSessions, archivedSessions, oldSessions, totalMessages, orphanedMessages }`
819
+
820
+ ## Integration with OpenClaw/Clawdbot
821
+
822
+ This package is designed to integrate with [Clawdbot](https://github.com/clawdbot/clawdbot):
823
+
824
+ ```typescript
825
+ // In your agent's AGENTS.md equivalent
826
+ // Instead of reading MEMORY.md, use:
827
+ const context = await memory.getContext(userMessage);
828
+ ```
829
+
830
+ ## Roadmap
831
+
832
+ ### ✅ Completed
833
+ - [x] CLI for memory management
834
+ - [x] Markdown import/export
835
+ - [x] Semantic search (OpenAI embeddings)
836
+ - [x] Hybrid search (vector + keyword)
837
+ - [x] Vector similarity functions
838
+ - [x] Automatic session summarization
839
+ - [x] Entity extraction from conversations
840
+ - [x] Session export/import (markdown)
841
+ - [x] Memory extraction from sessions
842
+ - [x] Task hierarchy (subtasks)
843
+ - [x] Learning application tracking
844
+ - [x] Context window budgeting & management
845
+ - [x] **Memory importance decay over time**
846
+ - [x] **Memory consolidation (merge similar)**
847
+ - [x] **Memory versioning (historical snapshots)**
848
+ - [x] **Memory tagging system**
849
+ - [x] **Auto-cleanup old sessions**
850
+ - [x] **Cleanup statistics & monitoring**
851
+
852
+ ### 🚧 In Progress
853
+ - [ ] Voyage AI embedding provider
854
+ - [ ] Local embeddings (transformers.js)
855
+ - [ ] Clawdbot skill integration
856
+
857
+ ### 📋 Planned
858
+ - [ ] Multi-agent memory sharing
859
+ - [ ] Entity relationship tracking table
860
+ - [ ] Memory migration tools (MEMORY.md → DB)
861
+ - [ ] Real-time subscriptions
862
+ - [ ] Memory access logging
863
+ - [ ] Memory reactions/ratings
864
+
865
+ ## Contributing
866
+
867
+ PRs welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md).
868
+
869
+ ## License
870
+
871
+ MIT