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.
@@ -0,0 +1,339 @@
1
+ "use strict";
2
+ /**
3
+ * Clawdbot Integration for OpenClaw Memory
4
+ *
5
+ * This module provides integration hooks for Clawdbot to:
6
+ * 1. Auto-log all messages to sessions
7
+ * 2. Replace memory_search with semantic recall
8
+ * 3. Replace memory_get with database queries
9
+ * 4. Inject relevant context into system prompts
10
+ * 5. Handle session lifecycle
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ClawdbotMemoryIntegration = void 0;
14
+ exports.createClawdbotIntegration = createClawdbotIntegration;
15
+ exports.createLoggingMiddleware = createLoggingMiddleware;
16
+ const index_1 = require("./index");
17
+ class ClawdbotMemoryIntegration {
18
+ memory;
19
+ config;
20
+ activeSessions;
21
+ sessionTimeoutMs;
22
+ constructor(config) {
23
+ this.config = config;
24
+ this.memory = new index_1.OpenClawMemory({
25
+ supabaseUrl: config.supabaseUrl,
26
+ supabaseKey: config.supabaseKey,
27
+ agentId: config.agentId,
28
+ embeddingProvider: config.embeddingProvider || 'openai',
29
+ openaiApiKey: config.openaiApiKey
30
+ });
31
+ this.activeSessions = new Map();
32
+ this.sessionTimeoutMs = config.sessionTimeout || 30 * 60 * 1000; // 30 minutes default
33
+ }
34
+ /**
35
+ * Initialize the memory system
36
+ */
37
+ async initialize() {
38
+ await this.memory.initialize();
39
+ }
40
+ /**
41
+ * Get or create a session for a chat/user
42
+ */
43
+ async getOrCreateSession(chatId, context = {}) {
44
+ // Check if active session exists
45
+ const existing = this.activeSessions.get(chatId);
46
+ const now = Date.now();
47
+ if (existing && (now - existing.lastActivity) < this.sessionTimeoutMs) {
48
+ // Update last activity
49
+ existing.lastActivity = now;
50
+ return existing.sessionId;
51
+ }
52
+ // End old session if it exists
53
+ if (existing) {
54
+ await this.endSession(chatId);
55
+ }
56
+ // Create new session
57
+ const session = await this.memory.startSession({
58
+ userId: context.userId || this.config.userId,
59
+ channel: context.channel,
60
+ metadata: {
61
+ chatId,
62
+ startedBy: 'clawdbot-integration'
63
+ }
64
+ });
65
+ this.activeSessions.set(chatId, {
66
+ sessionId: session.id,
67
+ lastActivity: now
68
+ });
69
+ return session.id;
70
+ }
71
+ /**
72
+ * Log a user message
73
+ */
74
+ async logUserMessage(chatId, content, context = {}) {
75
+ if (!this.config.autoLog)
76
+ return;
77
+ const sessionId = await this.getOrCreateSession(chatId, context);
78
+ await this.memory.addMessage(sessionId, {
79
+ role: 'user',
80
+ content,
81
+ metadata: {
82
+ messageId: context.messageId,
83
+ timestamp: context.timestamp || new Date().toISOString(),
84
+ channel: context.channel
85
+ }
86
+ });
87
+ }
88
+ /**
89
+ * Log an assistant message
90
+ */
91
+ async logAssistantMessage(chatId, content, context = {}) {
92
+ if (!this.config.autoLog)
93
+ return;
94
+ const sessionId = await this.getOrCreateSession(chatId, context);
95
+ await this.memory.addMessage(sessionId, {
96
+ role: 'assistant',
97
+ content,
98
+ metadata: {
99
+ messageId: context.messageId,
100
+ timestamp: context.timestamp || new Date().toISOString(),
101
+ model: context.model,
102
+ channel: context.channel
103
+ }
104
+ });
105
+ }
106
+ /**
107
+ * Log a system message
108
+ */
109
+ async logSystemMessage(chatId, content, context = {}) {
110
+ if (!this.config.autoLog)
111
+ return;
112
+ const sessionId = await this.getOrCreateSession(chatId, context);
113
+ await this.memory.addMessage(sessionId, {
114
+ role: 'system',
115
+ content,
116
+ metadata: {
117
+ timestamp: context.timestamp || new Date().toISOString()
118
+ }
119
+ });
120
+ }
121
+ /**
122
+ * Replace memory_search - semantic search for memories
123
+ */
124
+ async memorySearch(query, opts = {}) {
125
+ const results = await this.memory.recall(query, {
126
+ userId: opts.userId || this.config.userId,
127
+ category: opts.category,
128
+ limit: opts.limit || 5,
129
+ minImportance: opts.minImportance || 0.5
130
+ });
131
+ return results.map(r => ({
132
+ content: r.content,
133
+ category: r.category,
134
+ importance: r.importance,
135
+ created_at: r.created_at
136
+ }));
137
+ }
138
+ /**
139
+ * Replace memory_get - get memories by category
140
+ */
141
+ async memoryGet(opts = {}) {
142
+ const results = await this.memory.getMemories({
143
+ userId: opts.userId || this.config.userId,
144
+ category: opts.category,
145
+ limit: opts.limit || 10
146
+ });
147
+ return results.map(r => ({
148
+ content: r.content,
149
+ category: r.category,
150
+ importance: r.importance
151
+ }));
152
+ }
153
+ /**
154
+ * Build context for system prompt injection
155
+ */
156
+ async buildContext(query, opts = {}) {
157
+ const parts = [];
158
+ // Include relevant memories
159
+ if (opts.includeMemories !== false) {
160
+ const memories = await this.memorySearch(query, {
161
+ limit: opts.maxMemories || 5
162
+ });
163
+ if (memories.length > 0) {
164
+ parts.push('## Relevant Context\n');
165
+ memories.forEach(m => {
166
+ parts.push(`- [${m.category || 'general'}] ${m.content}`);
167
+ });
168
+ parts.push('');
169
+ }
170
+ }
171
+ // Include relevant learnings
172
+ if (opts.includeLearnings !== false) {
173
+ const learnings = await this.memory.getLearningRecommendations(query, opts.maxLearnings || 3);
174
+ if (learnings.length > 0) {
175
+ parts.push('## Past Learnings\n');
176
+ learnings.forEach(l => {
177
+ parts.push(`- [${l.category}] ${l.lesson}`);
178
+ if (l.action) {
179
+ parts.push(` Action: ${l.action}`);
180
+ }
181
+ });
182
+ parts.push('');
183
+ }
184
+ }
185
+ // Include recent messages from session
186
+ if (opts.includeRecentMessages && opts.chatId) {
187
+ const session = this.activeSessions.get(opts.chatId);
188
+ if (session) {
189
+ const messages = await this.memory.getMessages(session.sessionId, {
190
+ limit: opts.maxMessages || 10
191
+ });
192
+ if (messages.length > 0) {
193
+ parts.push('## Recent Conversation\n');
194
+ messages.slice(-5).forEach(m => {
195
+ const preview = m.content.length > 100
196
+ ? m.content.substring(0, 100) + '...'
197
+ : m.content;
198
+ parts.push(`- ${m.role}: ${preview}`);
199
+ });
200
+ parts.push('');
201
+ }
202
+ }
203
+ }
204
+ return parts.join('\n');
205
+ }
206
+ /**
207
+ * Store a memory
208
+ */
209
+ async remember(content, opts = {}) {
210
+ let sessionId;
211
+ if (opts.chatId) {
212
+ const session = this.activeSessions.get(opts.chatId);
213
+ sessionId = session?.sessionId;
214
+ }
215
+ return await this.memory.remember({
216
+ content,
217
+ category: opts.category,
218
+ importance: opts.importance || 0.5,
219
+ userId: opts.userId || this.config.userId,
220
+ sessionId,
221
+ expiresAt: opts.expiresAt
222
+ });
223
+ }
224
+ /**
225
+ * Record a learning
226
+ */
227
+ async learn(learning) {
228
+ let sessionId;
229
+ if (learning.chatId) {
230
+ const session = this.activeSessions.get(learning.chatId);
231
+ sessionId = session?.sessionId;
232
+ }
233
+ return await this.memory.learn({
234
+ category: learning.category,
235
+ trigger: learning.trigger,
236
+ lesson: learning.lesson,
237
+ action: learning.action,
238
+ severity: learning.severity || 'info',
239
+ sessionId
240
+ });
241
+ }
242
+ /**
243
+ * Create a task
244
+ */
245
+ async createTask(task) {
246
+ return await this.memory.createTask({
247
+ ...task,
248
+ userId: task.userId || this.config.userId
249
+ });
250
+ }
251
+ /**
252
+ * Get upcoming tasks for reminders
253
+ */
254
+ async getUpcomingTasks(hoursAhead = 24) {
255
+ return await this.memory.getTasksNeedingReminders({
256
+ userId: this.config.userId,
257
+ hoursAhead
258
+ });
259
+ }
260
+ /**
261
+ * End a session
262
+ */
263
+ async endSession(chatId, opts = {}) {
264
+ const session = this.activeSessions.get(chatId);
265
+ if (!session)
266
+ return;
267
+ // End session with optional summary
268
+ await this.memory.endSession(session.sessionId, {
269
+ summary: opts.summary,
270
+ autoSummarize: opts.autoSummarize !== false // Default true
271
+ });
272
+ // Extract memories if requested
273
+ if (opts.extractMemories) {
274
+ await this.memory.extractMemoriesFromSession(session.sessionId, {
275
+ autoExtract: true,
276
+ minImportance: 0.6
277
+ });
278
+ }
279
+ this.activeSessions.delete(chatId);
280
+ }
281
+ /**
282
+ * End all inactive sessions
283
+ */
284
+ async cleanupInactiveSessions() {
285
+ const now = Date.now();
286
+ const toEnd = [];
287
+ this.activeSessions.forEach((session, chatId) => {
288
+ if (now - session.lastActivity >= this.sessionTimeoutMs) {
289
+ toEnd.push(chatId);
290
+ }
291
+ });
292
+ for (const chatId of toEnd) {
293
+ await this.endSession(chatId, { autoSummarize: true });
294
+ }
295
+ }
296
+ /**
297
+ * Heartbeat check - call this periodically (e.g., every 30 min)
298
+ */
299
+ async heartbeat() {
300
+ // Clean up inactive sessions
301
+ await this.cleanupInactiveSessions();
302
+ // Get upcoming tasks
303
+ const upcomingTasks = await this.getUpcomingTasks(2); // Next 2 hours
304
+ return {
305
+ upcomingTasks,
306
+ inactiveSessions: this.activeSessions.size
307
+ };
308
+ }
309
+ /**
310
+ * Get the underlying OpenClawMemory instance for advanced operations
311
+ */
312
+ getMemory() {
313
+ return this.memory;
314
+ }
315
+ }
316
+ exports.ClawdbotMemoryIntegration = ClawdbotMemoryIntegration;
317
+ /**
318
+ * Factory function to create integration instance
319
+ */
320
+ function createClawdbotIntegration(config) {
321
+ return new ClawdbotMemoryIntegration(config);
322
+ }
323
+ /**
324
+ * Express/Koa-style middleware for auto-logging
325
+ */
326
+ function createLoggingMiddleware(integration) {
327
+ return async (message) => {
328
+ const { chatId, role, content, context = {} } = message;
329
+ if (role === 'user') {
330
+ await integration.logUserMessage(chatId, content, context);
331
+ }
332
+ else if (role === 'assistant') {
333
+ await integration.logAssistantMessage(chatId, content, context);
334
+ }
335
+ else if (role === 'system') {
336
+ await integration.logSystemMessage(chatId, content, context);
337
+ }
338
+ };
339
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};