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/LICENSE +21 -0
- package/README.md +871 -0
- package/SCHEMA.md +215 -0
- package/dist/clawdbot-integration.d.ts +171 -0
- package/dist/clawdbot-integration.js +339 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1815 -0
- package/dist/context-manager.d.ts +143 -0
- package/dist/context-manager.js +360 -0
- package/dist/error-handling.d.ts +100 -0
- package/dist/error-handling.js +301 -0
- package/dist/index.d.ts +735 -0
- package/dist/index.js +2256 -0
- package/dist/parsers.d.ts +115 -0
- package/dist/parsers.js +406 -0
- package/migrations/001_initial.sql +153 -0
- package/migrations/002_vector_search.sql +219 -0
- package/migrations/003_entity_relationships.sql +143 -0
- package/package.json +66 -0
package/SCHEMA.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# OpenClaw Memory - Database Schema
|
|
2
|
+
|
|
3
|
+
## Core Tables
|
|
4
|
+
|
|
5
|
+
### 1. `sessions`
|
|
6
|
+
Every conversation gets a session. This is the primary organizational unit.
|
|
7
|
+
|
|
8
|
+
```sql
|
|
9
|
+
CREATE TABLE sessions (
|
|
10
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
11
|
+
agent_id TEXT NOT NULL, -- Which agent (main, subagent, etc.)
|
|
12
|
+
user_id TEXT, -- Who they're talking to
|
|
13
|
+
channel TEXT, -- telegram, discord, webchat, etc.
|
|
14
|
+
started_at TIMESTAMPTZ DEFAULT NOW(),
|
|
15
|
+
ended_at TIMESTAMPTZ,
|
|
16
|
+
summary TEXT, -- AI-generated session summary
|
|
17
|
+
metadata JSONB DEFAULT '{}' -- Flexible additional data
|
|
18
|
+
);
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 2. `messages`
|
|
22
|
+
Every message in every session. The raw conversation log.
|
|
23
|
+
|
|
24
|
+
```sql
|
|
25
|
+
CREATE TABLE messages (
|
|
26
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
27
|
+
session_id UUID REFERENCES sessions(id) ON DELETE CASCADE,
|
|
28
|
+
role TEXT NOT NULL, -- 'user', 'assistant', 'system', 'tool'
|
|
29
|
+
content TEXT NOT NULL,
|
|
30
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
31
|
+
token_count INT, -- Track usage
|
|
32
|
+
metadata JSONB DEFAULT '{}' -- Tool calls, attachments, etc.
|
|
33
|
+
);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 3. `memories`
|
|
37
|
+
Distilled, long-term memories. The "important stuff" extracted from sessions.
|
|
38
|
+
|
|
39
|
+
```sql
|
|
40
|
+
CREATE TABLE memories (
|
|
41
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
42
|
+
agent_id TEXT NOT NULL,
|
|
43
|
+
user_id TEXT, -- Whose memory (null = global)
|
|
44
|
+
category TEXT, -- 'preference', 'fact', 'decision', 'task', etc.
|
|
45
|
+
content TEXT NOT NULL,
|
|
46
|
+
importance FLOAT DEFAULT 0.5, -- 0-1 score for retrieval prioritization
|
|
47
|
+
source_session_id UUID REFERENCES sessions(id),
|
|
48
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
49
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
50
|
+
expires_at TIMESTAMPTZ, -- Optional TTL for temporary memories
|
|
51
|
+
embedding VECTOR(1536), -- For semantic search (OpenAI ada-002 dimensions)
|
|
52
|
+
metadata JSONB DEFAULT '{}'
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
-- Index for vector similarity search
|
|
56
|
+
CREATE INDEX memories_embedding_idx ON memories
|
|
57
|
+
USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 4. `entities`
|
|
61
|
+
People, places, things the agent knows about.
|
|
62
|
+
|
|
63
|
+
```sql
|
|
64
|
+
CREATE TABLE entities (
|
|
65
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
66
|
+
agent_id TEXT NOT NULL,
|
|
67
|
+
entity_type TEXT NOT NULL, -- 'person', 'place', 'project', 'tool', etc.
|
|
68
|
+
name TEXT NOT NULL,
|
|
69
|
+
aliases TEXT[], -- Alternative names
|
|
70
|
+
description TEXT,
|
|
71
|
+
properties JSONB DEFAULT '{}', -- Flexible key-value properties
|
|
72
|
+
first_seen_at TIMESTAMPTZ DEFAULT NOW(),
|
|
73
|
+
last_seen_at TIMESTAMPTZ DEFAULT NOW(),
|
|
74
|
+
mention_count INT DEFAULT 1,
|
|
75
|
+
embedding VECTOR(1536),
|
|
76
|
+
|
|
77
|
+
UNIQUE(agent_id, entity_type, name)
|
|
78
|
+
);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 5. `tasks`
|
|
82
|
+
Persistent task tracking (replaces TODO.md).
|
|
83
|
+
|
|
84
|
+
```sql
|
|
85
|
+
CREATE TABLE tasks (
|
|
86
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
87
|
+
agent_id TEXT NOT NULL,
|
|
88
|
+
user_id TEXT,
|
|
89
|
+
title TEXT NOT NULL,
|
|
90
|
+
description TEXT,
|
|
91
|
+
status TEXT DEFAULT 'pending', -- 'pending', 'in_progress', 'blocked', 'done'
|
|
92
|
+
priority INT DEFAULT 0,
|
|
93
|
+
due_at TIMESTAMPTZ,
|
|
94
|
+
completed_at TIMESTAMPTZ,
|
|
95
|
+
source_session_id UUID REFERENCES sessions(id),
|
|
96
|
+
parent_task_id UUID REFERENCES tasks(id),
|
|
97
|
+
metadata JSONB DEFAULT '{}',
|
|
98
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
99
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
100
|
+
);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 6. `learnings`
|
|
104
|
+
Self-improvement records (replaces LEARNINGS.md).
|
|
105
|
+
|
|
106
|
+
```sql
|
|
107
|
+
CREATE TABLE learnings (
|
|
108
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
109
|
+
agent_id TEXT NOT NULL,
|
|
110
|
+
category TEXT NOT NULL, -- 'error', 'correction', 'improvement', 'capability_gap'
|
|
111
|
+
trigger TEXT NOT NULL, -- What caused this learning
|
|
112
|
+
lesson TEXT NOT NULL, -- What was learned
|
|
113
|
+
action TEXT, -- What to do differently
|
|
114
|
+
severity TEXT DEFAULT 'info', -- 'info', 'warning', 'critical'
|
|
115
|
+
source_session_id UUID REFERENCES sessions(id),
|
|
116
|
+
applied_count INT DEFAULT 0, -- How many times this learning was used
|
|
117
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
118
|
+
metadata JSONB DEFAULT '{}'
|
|
119
|
+
);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Key Features
|
|
123
|
+
|
|
124
|
+
### 1. Session Summarization
|
|
125
|
+
When a session ends (or grows too long), automatically summarize it:
|
|
126
|
+
- Extract key decisions
|
|
127
|
+
- Note new entities/relationships
|
|
128
|
+
- Create memories from important facts
|
|
129
|
+
- Store summary in session record
|
|
130
|
+
|
|
131
|
+
### 2. Semantic Memory Search
|
|
132
|
+
Instead of loading entire MEMORY.md:
|
|
133
|
+
```sql
|
|
134
|
+
-- Find relevant memories for current context
|
|
135
|
+
SELECT content, importance, created_at
|
|
136
|
+
FROM memories
|
|
137
|
+
WHERE agent_id = $1
|
|
138
|
+
ORDER BY embedding <=> $2 -- Vector similarity
|
|
139
|
+
LIMIT 10;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 3. Context Window Management
|
|
143
|
+
Before each response, pull relevant context:
|
|
144
|
+
- Recent messages from current session
|
|
145
|
+
- Relevant memories (semantic search)
|
|
146
|
+
- Active tasks
|
|
147
|
+
- Entity info for mentioned people/things
|
|
148
|
+
|
|
149
|
+
### 4. Multi-Agent Memory Sharing
|
|
150
|
+
Agents can share memories:
|
|
151
|
+
```sql
|
|
152
|
+
-- Get memories shared across all agents
|
|
153
|
+
SELECT * FROM memories
|
|
154
|
+
WHERE agent_id = 'shared'
|
|
155
|
+
AND user_id = $1;
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Migration Strategy
|
|
159
|
+
|
|
160
|
+
### From Markdown to Supabase
|
|
161
|
+
1. Parse existing MEMORY.md → memories table
|
|
162
|
+
2. Parse daily logs → sessions + messages
|
|
163
|
+
3. Parse TODO.md → tasks table
|
|
164
|
+
4. Parse LEARNINGS.md → learnings table
|
|
165
|
+
5. Keep markdown as backup/fallback
|
|
166
|
+
|
|
167
|
+
## API Design (npm package)
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { OpenClawMemory } from 'openclaw-memory';
|
|
171
|
+
|
|
172
|
+
const memory = new OpenClawMemory({
|
|
173
|
+
supabaseUrl: process.env.SUPABASE_URL,
|
|
174
|
+
supabaseKey: process.env.SUPABASE_KEY,
|
|
175
|
+
agentId: 'main'
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Start a session
|
|
179
|
+
const session = await memory.startSession({
|
|
180
|
+
userId: 'han',
|
|
181
|
+
channel: 'telegram'
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Log messages
|
|
185
|
+
await memory.addMessage(session.id, {
|
|
186
|
+
role: 'user',
|
|
187
|
+
content: 'Hello!'
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Create a memory
|
|
191
|
+
await memory.remember({
|
|
192
|
+
content: 'Han prefers concise responses',
|
|
193
|
+
category: 'preference',
|
|
194
|
+
importance: 0.8
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Search memories
|
|
198
|
+
const relevant = await memory.recall('user preferences', { limit: 5 });
|
|
199
|
+
|
|
200
|
+
// End session with summary
|
|
201
|
+
await memory.endSession(session.id, {
|
|
202
|
+
summary: 'Discussed project requirements...'
|
|
203
|
+
});
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Benefits Summary
|
|
207
|
+
|
|
208
|
+
| Problem | Solution |
|
|
209
|
+
|---------|----------|
|
|
210
|
+
| Context window limits | Only load relevant memories via semantic search |
|
|
211
|
+
| Forgetting across sessions | Persistent database with session history |
|
|
212
|
+
| Unstructured data | SQL queries, typed schemas, relationships |
|
|
213
|
+
| No search | pgvector semantic search + full-text search |
|
|
214
|
+
| Single agent | Multi-agent memory sharing |
|
|
215
|
+
| Manual memory curation | Auto-extract from conversations |
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clawdbot Integration for OpenClaw Memory
|
|
3
|
+
*
|
|
4
|
+
* This module provides integration hooks for Clawdbot to:
|
|
5
|
+
* 1. Auto-log all messages to sessions
|
|
6
|
+
* 2. Replace memory_search with semantic recall
|
|
7
|
+
* 3. Replace memory_get with database queries
|
|
8
|
+
* 4. Inject relevant context into system prompts
|
|
9
|
+
* 5. Handle session lifecycle
|
|
10
|
+
*/
|
|
11
|
+
import { OpenClawMemory, Memory, Learning, Task } from './index';
|
|
12
|
+
export interface ClawdbotConfig {
|
|
13
|
+
supabaseUrl: string;
|
|
14
|
+
supabaseKey: string;
|
|
15
|
+
agentId: string;
|
|
16
|
+
userId?: string;
|
|
17
|
+
embeddingProvider?: 'openai' | 'voyage' | 'none';
|
|
18
|
+
openaiApiKey?: string;
|
|
19
|
+
autoLog?: boolean;
|
|
20
|
+
autoInject?: boolean;
|
|
21
|
+
sessionTimeout?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface MessageContext {
|
|
24
|
+
sessionId?: string;
|
|
25
|
+
userId?: string;
|
|
26
|
+
channel?: string;
|
|
27
|
+
messageId?: string;
|
|
28
|
+
timestamp?: string;
|
|
29
|
+
model?: string;
|
|
30
|
+
}
|
|
31
|
+
export declare class ClawdbotMemoryIntegration {
|
|
32
|
+
private memory;
|
|
33
|
+
private config;
|
|
34
|
+
private activeSessions;
|
|
35
|
+
private sessionTimeoutMs;
|
|
36
|
+
constructor(config: ClawdbotConfig);
|
|
37
|
+
/**
|
|
38
|
+
* Initialize the memory system
|
|
39
|
+
*/
|
|
40
|
+
initialize(): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Get or create a session for a chat/user
|
|
43
|
+
*/
|
|
44
|
+
getOrCreateSession(chatId: string, context?: MessageContext): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Log a user message
|
|
47
|
+
*/
|
|
48
|
+
logUserMessage(chatId: string, content: string, context?: MessageContext): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Log an assistant message
|
|
51
|
+
*/
|
|
52
|
+
logAssistantMessage(chatId: string, content: string, context?: MessageContext): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Log a system message
|
|
55
|
+
*/
|
|
56
|
+
logSystemMessage(chatId: string, content: string, context?: MessageContext): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Replace memory_search - semantic search for memories
|
|
59
|
+
*/
|
|
60
|
+
memorySearch(query: string, opts?: {
|
|
61
|
+
userId?: string;
|
|
62
|
+
category?: string;
|
|
63
|
+
limit?: number;
|
|
64
|
+
minImportance?: number;
|
|
65
|
+
}): Promise<Array<{
|
|
66
|
+
content: string;
|
|
67
|
+
category?: string;
|
|
68
|
+
importance: number;
|
|
69
|
+
created_at: string;
|
|
70
|
+
}>>;
|
|
71
|
+
/**
|
|
72
|
+
* Replace memory_get - get memories by category
|
|
73
|
+
*/
|
|
74
|
+
memoryGet(opts?: {
|
|
75
|
+
category?: string;
|
|
76
|
+
userId?: string;
|
|
77
|
+
limit?: number;
|
|
78
|
+
}): Promise<Array<{
|
|
79
|
+
content: string;
|
|
80
|
+
category?: string;
|
|
81
|
+
importance: number;
|
|
82
|
+
}>>;
|
|
83
|
+
/**
|
|
84
|
+
* Build context for system prompt injection
|
|
85
|
+
*/
|
|
86
|
+
buildContext(query: string, opts?: {
|
|
87
|
+
includeMemories?: boolean;
|
|
88
|
+
includeLearnings?: boolean;
|
|
89
|
+
includeRecentMessages?: boolean;
|
|
90
|
+
chatId?: string;
|
|
91
|
+
maxMemories?: number;
|
|
92
|
+
maxLearnings?: number;
|
|
93
|
+
maxMessages?: number;
|
|
94
|
+
}): Promise<string>;
|
|
95
|
+
/**
|
|
96
|
+
* Store a memory
|
|
97
|
+
*/
|
|
98
|
+
remember(content: string, opts?: {
|
|
99
|
+
category?: string;
|
|
100
|
+
importance?: number;
|
|
101
|
+
userId?: string;
|
|
102
|
+
chatId?: string;
|
|
103
|
+
expiresAt?: string;
|
|
104
|
+
}): Promise<Memory>;
|
|
105
|
+
/**
|
|
106
|
+
* Record a learning
|
|
107
|
+
*/
|
|
108
|
+
learn(learning: {
|
|
109
|
+
category: 'error' | 'correction' | 'improvement' | 'capability_gap';
|
|
110
|
+
trigger: string;
|
|
111
|
+
lesson: string;
|
|
112
|
+
action?: string;
|
|
113
|
+
severity?: 'info' | 'warning' | 'critical';
|
|
114
|
+
chatId?: string;
|
|
115
|
+
}): Promise<Learning>;
|
|
116
|
+
/**
|
|
117
|
+
* Create a task
|
|
118
|
+
*/
|
|
119
|
+
createTask(task: {
|
|
120
|
+
title: string;
|
|
121
|
+
description?: string;
|
|
122
|
+
priority?: number;
|
|
123
|
+
dueAt?: string;
|
|
124
|
+
userId?: string;
|
|
125
|
+
parentTaskId?: string;
|
|
126
|
+
}): Promise<Task>;
|
|
127
|
+
/**
|
|
128
|
+
* Get upcoming tasks for reminders
|
|
129
|
+
*/
|
|
130
|
+
getUpcomingTasks(hoursAhead?: number): Promise<Array<Task & {
|
|
131
|
+
timeUntilDue: number;
|
|
132
|
+
}>>;
|
|
133
|
+
/**
|
|
134
|
+
* End a session
|
|
135
|
+
*/
|
|
136
|
+
endSession(chatId: string, opts?: {
|
|
137
|
+
summary?: string;
|
|
138
|
+
autoSummarize?: boolean;
|
|
139
|
+
extractMemories?: boolean;
|
|
140
|
+
}): Promise<void>;
|
|
141
|
+
/**
|
|
142
|
+
* End all inactive sessions
|
|
143
|
+
*/
|
|
144
|
+
cleanupInactiveSessions(): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Heartbeat check - call this periodically (e.g., every 30 min)
|
|
147
|
+
*/
|
|
148
|
+
heartbeat(): Promise<{
|
|
149
|
+
upcomingTasks: Array<Task & {
|
|
150
|
+
timeUntilDue: number;
|
|
151
|
+
}>;
|
|
152
|
+
inactiveSessions: number;
|
|
153
|
+
}>;
|
|
154
|
+
/**
|
|
155
|
+
* Get the underlying OpenClawMemory instance for advanced operations
|
|
156
|
+
*/
|
|
157
|
+
getMemory(): OpenClawMemory;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Factory function to create integration instance
|
|
161
|
+
*/
|
|
162
|
+
export declare function createClawdbotIntegration(config: ClawdbotConfig): ClawdbotMemoryIntegration;
|
|
163
|
+
/**
|
|
164
|
+
* Express/Koa-style middleware for auto-logging
|
|
165
|
+
*/
|
|
166
|
+
export declare function createLoggingMiddleware(integration: ClawdbotMemoryIntegration): (message: {
|
|
167
|
+
chatId: string;
|
|
168
|
+
role: "user" | "assistant" | "system";
|
|
169
|
+
content: string;
|
|
170
|
+
context?: MessageContext;
|
|
171
|
+
}) => Promise<void>;
|