claude-flow 2.7.38 → 2.7.40

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.
@@ -1,477 +1,409 @@
1
- import { SharedMemory } from './shared-memory.js';
2
- const SWARM_NAMESPACES = {
3
- AGENTS: 'swarm:agents',
4
- TASKS: 'swarm:tasks',
5
- COMMUNICATIONS: 'swarm:communications',
6
- CONSENSUS: 'swarm:consensus',
7
- PATTERNS: 'swarm:patterns',
8
- METRICS: 'swarm:metrics',
9
- COORDINATION: 'swarm:coordination'
10
- };
11
- export class SwarmMemory extends SharedMemory {
12
- constructor(options = {}){
13
- super({
14
- directory: options.directory || '.swarm',
15
- filename: options.filename || 'swarm-memory.db',
16
- ...options
17
- });
18
- this.swarmId = options.swarmId || 'default';
19
- this.mcpMode = options.mcpMode !== false;
20
- this.agentCache = new Map();
21
- this.taskCache = new Map();
22
- this.patternCache = new Map();
1
+ import { EventEmitter } from 'node:events';
2
+ import { Logger } from '../core/logger.js';
3
+ import { MemoryManager } from './manager.js';
4
+ import { EventBus } from '../core/event-bus.js';
5
+ import { generateId } from '../utils/helpers.js';
6
+ import * as fs from 'node:fs/promises';
7
+ import * as path from 'node:path';
8
+ export class SwarmMemoryManager extends EventEmitter {
9
+ logger;
10
+ config;
11
+ baseMemory;
12
+ entries;
13
+ knowledgeBases;
14
+ agentMemories;
15
+ syncTimer;
16
+ isInitialized = false;
17
+ constructor(config = {}){
18
+ super();
19
+ this.logger = new Logger('SwarmMemoryManager');
20
+ this.config = {
21
+ namespace: 'swarm',
22
+ enableDistribution: true,
23
+ enableReplication: true,
24
+ syncInterval: 10000,
25
+ maxEntries: 10000,
26
+ compressionThreshold: 1000,
27
+ enableKnowledgeBase: true,
28
+ enableCrossAgentSharing: true,
29
+ persistencePath: './swarm-memory',
30
+ ...config
31
+ };
32
+ this.entries = new Map();
33
+ this.knowledgeBases = new Map();
34
+ this.agentMemories = new Map();
35
+ const eventBus = EventBus.getInstance();
36
+ this.baseMemory = new MemoryManager({
37
+ backend: 'sqlite',
38
+ namespace: this.config.namespace,
39
+ cacheSizeMB: 50,
40
+ syncOnExit: true,
41
+ maxEntries: this.config.maxEntries,
42
+ ttlMinutes: 60
43
+ }, eventBus, this.logger);
23
44
  }
24
45
  async initialize() {
25
- await super.initialize();
26
- await this._initializeSwarmNamespaces();
27
- await this._loadSwarmState();
28
- this.emit('swarm:initialized', {
29
- swarmId: this.swarmId
46
+ if (this.isInitialized) return;
47
+ this.logger.info('Initializing swarm memory manager...');
48
+ await this.baseMemory.initialize();
49
+ await fs.mkdir(this.config.persistencePath, {
50
+ recursive: true
30
51
  });
52
+ await this.loadMemoryState();
53
+ if (this.config.syncInterval > 0) {
54
+ this.syncTimer = setInterval(()=>{
55
+ this.syncMemoryState();
56
+ }, this.config.syncInterval);
57
+ }
58
+ this.isInitialized = true;
59
+ this.emit('memory:initialized');
31
60
  }
32
- async storeAgent(agentId, agentData) {
33
- const key = `agent:${agentId}`;
34
- const enrichedData = {
35
- ...agentData,
36
- swarmId: this.swarmId,
37
- lastUpdated: new Date().toISOString()
38
- };
39
- await this.store(key, enrichedData, {
40
- namespace: SWARM_NAMESPACES.AGENTS,
41
- tags: [
42
- 'agent',
43
- agentData.type,
44
- agentData.status
45
- ],
61
+ async shutdown() {
62
+ if (!this.isInitialized) return;
63
+ this.logger.info('Shutting down swarm memory manager...');
64
+ if (this.syncTimer) {
65
+ clearInterval(this.syncTimer);
66
+ this.syncTimer = undefined;
67
+ }
68
+ await this.saveMemoryState();
69
+ this.isInitialized = false;
70
+ this.emit('memory:shutdown');
71
+ }
72
+ async remember(agentId, type, content, metadata = {}) {
73
+ const entryId = generateId('mem');
74
+ const entry = {
75
+ id: entryId,
76
+ agentId,
77
+ type,
78
+ content,
79
+ timestamp: new Date(),
46
80
  metadata: {
47
- swarmId: this.swarmId,
48
- agentType: agentData.type
81
+ shareLevel: 'team',
82
+ priority: 1,
83
+ ...metadata
49
84
  }
50
- });
51
- this.agentCache.set(agentId, enrichedData);
52
- this.emit('swarm:agentStored', {
53
- agentId,
54
- type: agentData.type
55
- });
56
- return {
57
- agentId,
58
- stored: true
59
85
  };
60
- }
61
- async getAgent(agentId) {
62
- if (this.agentCache.has(agentId)) {
63
- return this.agentCache.get(agentId);
64
- }
65
- const key = `agent:${agentId}`;
66
- const agent = await this.retrieve(key, SWARM_NAMESPACES.AGENTS);
67
- if (agent) {
68
- this.agentCache.set(agentId, agent);
86
+ this.entries.set(entryId, entry);
87
+ if (!this.agentMemories.has(agentId)) {
88
+ this.agentMemories.set(agentId, new Set());
69
89
  }
70
- return agent;
71
- }
72
- async listAgents(filter = {}) {
73
- const agents = await this.list(SWARM_NAMESPACES.AGENTS, {
74
- limit: filter.limit || 100
75
- });
76
- return agents.map((entry)=>entry.value).filter((agent)=>{
77
- if (filter.type && agent.type !== filter.type) return false;
78
- if (filter.status && agent.status !== filter.status) return false;
79
- if (filter.swarmId && agent.swarmId !== filter.swarmId) return false;
80
- return true;
81
- });
82
- }
83
- async storeTask(taskId, taskData) {
84
- const key = `task:${taskId}`;
85
- const enrichedData = {
86
- ...taskData,
87
- swarmId: this.swarmId,
88
- createdAt: taskData.createdAt || new Date().toISOString(),
89
- updatedAt: new Date().toISOString()
90
- };
91
- await this.store(key, enrichedData, {
92
- namespace: SWARM_NAMESPACES.TASKS,
93
- tags: [
94
- 'task',
95
- taskData.status,
96
- taskData.priority
97
- ],
90
+ this.agentMemories.get(agentId).add(entryId);
91
+ await this.baseMemory.remember({
92
+ namespace: this.config.namespace,
93
+ key: `entry:${entryId}`,
94
+ content: JSON.stringify(entry),
98
95
  metadata: {
99
- swarmId: this.swarmId,
100
- assignedAgents: taskData.assignedAgents || []
96
+ type: 'swarm-memory',
97
+ agentId,
98
+ entryType: type,
99
+ shareLevel: entry.metadata.shareLevel
101
100
  }
102
101
  });
103
- this.taskCache.set(taskId, enrichedData);
104
- this.emit('swarm:taskStored', {
105
- taskId,
106
- status: taskData.status
107
- });
108
- return {
109
- taskId,
110
- stored: true
111
- };
102
+ this.logger.debug(`Agent ${agentId} remembered: ${type} - ${entryId}`);
103
+ this.emit('memory:added', entry);
104
+ if (type === 'knowledge' && this.config.enableKnowledgeBase) {
105
+ await this.updateKnowledgeBase(entry);
106
+ }
107
+ await this.enforceMemoryLimits();
108
+ return entryId;
112
109
  }
113
- async updateTaskStatus(taskId, status, result = null) {
114
- const task = await this.getTask(taskId);
115
- if (!task) {
116
- throw new Error(`Task ${taskId} not found`);
110
+ async recall(query) {
111
+ let results = Array.from(this.entries.values());
112
+ if (query.agentId) {
113
+ results = results.filter((e)=>e.agentId === query.agentId);
117
114
  }
118
- task.status = status;
119
- task.updatedAt = new Date().toISOString();
120
- if (result) {
121
- task.result = result;
115
+ if (query.type) {
116
+ results = results.filter((e)=>e.type === query.type);
122
117
  }
123
- if (status === 'completed') {
124
- task.completedAt = new Date().toISOString();
118
+ if (query.taskId) {
119
+ results = results.filter((e)=>e.metadata.taskId === query.taskId);
125
120
  }
126
- await this.storeTask(taskId, task);
127
- this.emit('swarm:taskStatusUpdated', {
128
- taskId,
129
- status
130
- });
131
- return {
132
- taskId,
133
- status,
134
- updated: true
135
- };
136
- }
137
- async getTask(taskId) {
138
- if (this.taskCache.has(taskId)) {
139
- return this.taskCache.get(taskId);
121
+ if (query.objectiveId) {
122
+ results = results.filter((e)=>e.metadata.objectiveId === query.objectiveId);
140
123
  }
141
- const key = `task:${taskId}`;
142
- const task = await this.retrieve(key, SWARM_NAMESPACES.TASKS);
143
- if (task) {
144
- this.taskCache.set(taskId, task);
124
+ if (query.tags && query.tags.length > 0) {
125
+ results = results.filter((e)=>e.metadata.tags && query.tags.some((tag)=>e.metadata.tags.includes(tag)));
145
126
  }
146
- return task;
147
- }
148
- async storeCommunication(fromAgent, toAgent, message) {
149
- const commId = `comm:${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
150
- const communication = {
151
- id: commId,
152
- fromAgent,
153
- toAgent,
154
- message,
155
- swarmId: this.swarmId,
156
- timestamp: new Date().toISOString()
157
- };
158
- await this.store(commId, communication, {
159
- namespace: SWARM_NAMESPACES.COMMUNICATIONS,
160
- ttl: 86400,
161
- tags: [
162
- 'communication',
163
- message.type
164
- ],
165
- metadata: {
166
- fromAgent,
167
- toAgent,
168
- messageType: message.type
169
- }
170
- });
171
- this.emit('swarm:communication', {
172
- fromAgent,
173
- toAgent,
174
- type: message.type
175
- });
176
- return {
177
- id: commId,
178
- stored: true
179
- };
127
+ if (query.since) {
128
+ results = results.filter((e)=>e.timestamp >= query.since);
129
+ }
130
+ if (query.before) {
131
+ results = results.filter((e)=>e.timestamp <= query.before);
132
+ }
133
+ if (query.shareLevel) {
134
+ results = results.filter((e)=>e.metadata.shareLevel === query.shareLevel);
135
+ }
136
+ results.sort((a, b)=>b.timestamp.getTime() - a.timestamp.getTime());
137
+ if (query.limit) {
138
+ results = results.slice(0, query.limit);
139
+ }
140
+ this.logger.debug(`Recalled ${results.length} memories for query`);
141
+ return results;
180
142
  }
181
- async storeConsensus(consensusId, decision) {
182
- const key = `consensus:${consensusId}`;
183
- const consensusData = {
184
- ...decision,
185
- swarmId: this.swarmId,
186
- timestamp: new Date().toISOString()
187
- };
188
- await this.store(key, consensusData, {
189
- namespace: SWARM_NAMESPACES.CONSENSUS,
190
- tags: [
191
- 'consensus',
192
- decision.status
193
- ],
143
+ async shareMemory(entryId, targetAgentId) {
144
+ const entry = this.entries.get(entryId);
145
+ if (!entry) {
146
+ throw new Error('Memory entry not found');
147
+ }
148
+ if (!this.config.enableCrossAgentSharing) {
149
+ throw new Error('Cross-agent sharing is disabled');
150
+ }
151
+ if (entry.metadata.shareLevel === 'private') {
152
+ throw new Error('Memory entry is private and cannot be shared');
153
+ }
154
+ const sharedEntry = {
155
+ ...entry,
156
+ id: generateId('mem'),
194
157
  metadata: {
195
- swarmId: this.swarmId,
196
- taskId: decision.taskId,
197
- threshold: decision.threshold
158
+ ...entry.metadata,
159
+ originalId: entryId,
160
+ sharedFrom: entry.agentId,
161
+ sharedTo: targetAgentId,
162
+ sharedAt: new Date()
198
163
  }
199
- });
200
- this.emit('swarm:consensus', {
201
- consensusId,
202
- status: decision.status
203
- });
204
- return {
205
- consensusId,
206
- stored: true
207
- };
208
- }
209
- async storePattern(patternId, pattern) {
210
- const key = `pattern:${patternId}`;
211
- const patternData = {
212
- ...pattern,
213
- swarmId: this.swarmId,
214
- createdAt: new Date().toISOString(),
215
- usageCount: 0,
216
- successRate: 0
217
164
  };
218
- await this.store(key, patternData, {
219
- namespace: SWARM_NAMESPACES.PATTERNS,
220
- tags: [
221
- 'pattern',
222
- pattern.type
223
- ],
224
- metadata: {
225
- swarmId: this.swarmId,
226
- patternType: pattern.type,
227
- confidence: pattern.confidence || 0
228
- }
229
- });
230
- if (pattern.type === 'coordination' || pattern.type === 'optimization') {
231
- this.patternCache.set(patternId, patternData);
165
+ this.entries.set(sharedEntry.id, sharedEntry);
166
+ if (!this.agentMemories.has(targetAgentId)) {
167
+ this.agentMemories.set(targetAgentId, new Set());
232
168
  }
233
- this.emit('swarm:patternStored', {
234
- patternId,
235
- type: pattern.type
169
+ this.agentMemories.get(targetAgentId).add(sharedEntry.id);
170
+ this.logger.info(`Shared memory ${entryId} from ${entry.agentId} to ${targetAgentId}`);
171
+ this.emit('memory:shared', {
172
+ original: entry,
173
+ shared: sharedEntry
236
174
  });
237
- return {
238
- patternId,
239
- stored: true
240
- };
241
175
  }
242
- async updatePatternMetrics(patternId, success = true) {
243
- const pattern = await this.getPattern(patternId);
244
- if (!pattern) {
245
- throw new Error(`Pattern ${patternId} not found`);
176
+ async broadcastMemory(entryId, agentIds) {
177
+ const entry = this.entries.get(entryId);
178
+ if (!entry) {
179
+ throw new Error('Memory entry not found');
246
180
  }
247
- pattern.usageCount++;
248
- pattern.lastUsedAt = new Date().toISOString();
249
- const alpha = 0.1;
250
- const currentSuccess = success ? 1 : 0;
251
- pattern.successRate = alpha * currentSuccess + (1 - alpha) * (pattern.successRate || 0);
252
- await this.storePattern(patternId, pattern);
253
- return {
254
- patternId,
255
- usageCount: pattern.usageCount,
256
- successRate: pattern.successRate
257
- };
258
- }
259
- async getPattern(patternId) {
260
- if (this.patternCache.has(patternId)) {
261
- return this.patternCache.get(patternId);
181
+ if (entry.metadata.shareLevel === 'private') {
182
+ throw new Error('Cannot broadcast private memory');
262
183
  }
263
- const key = `pattern:${patternId}`;
264
- return await this.retrieve(key, SWARM_NAMESPACES.PATTERNS);
265
- }
266
- async findBestPatterns(context, limit = 5) {
267
- const patterns = await this.search({
268
- namespace: SWARM_NAMESPACES.PATTERNS,
269
- tags: context.tags,
270
- limit: 100
271
- });
272
- const scored = patterns.map((entry)=>{
273
- const pattern = entry.value;
274
- const score = pattern.successRate * 0.7 + (pattern.confidence || 0) * 0.2 + (pattern.usageCount > 0 ? 0.1 : 0);
275
- return {
276
- ...pattern,
277
- score
278
- };
279
- });
280
- return scored.sort((a, b)=>b.score - a.score).slice(0, limit);
184
+ const targets = agentIds || Array.from(this.agentMemories.keys()).filter((id)=>id !== entry.agentId);
185
+ for (const targetId of targets){
186
+ try {
187
+ await this.shareMemory(entryId, targetId);
188
+ } catch (error) {
189
+ this.logger.warn(`Failed to share memory to ${targetId}:`, error);
190
+ }
191
+ }
192
+ this.logger.info(`Broadcasted memory ${entryId} to ${targets.length} agents`);
281
193
  }
282
- async storeCoordination(key, state) {
283
- await this.store(key, state, {
284
- namespace: SWARM_NAMESPACES.COORDINATION,
285
- ttl: 3600,
194
+ async createKnowledgeBase(name, description, domain, expertise) {
195
+ const kbId = generateId('kb');
196
+ const knowledgeBase = {
197
+ id: kbId,
198
+ name,
199
+ description,
200
+ entries: [],
286
201
  metadata: {
287
- swarmId: this.swarmId,
288
- timestamp: new Date().toISOString()
202
+ domain,
203
+ expertise,
204
+ contributors: [],
205
+ lastUpdated: new Date()
289
206
  }
290
- });
291
- return {
292
- key,
293
- stored: true
294
207
  };
208
+ this.knowledgeBases.set(kbId, knowledgeBase);
209
+ this.logger.info(`Created knowledge base: ${name} (${kbId})`);
210
+ this.emit('knowledgebase:created', knowledgeBase);
211
+ return kbId;
295
212
  }
296
- async getCoordination(key) {
297
- return await this.retrieve(key, SWARM_NAMESPACES.COORDINATION);
213
+ async updateKnowledgeBase(entry) {
214
+ if (!this.config.enableKnowledgeBase) return;
215
+ const relevantKBs = Array.from(this.knowledgeBases.values()).filter((kb)=>{
216
+ const tags = entry.metadata.tags || [];
217
+ return tags.some((tag)=>kb.metadata.expertise.some((exp)=>exp.toLowerCase().includes(tag.toLowerCase()) || tag.toLowerCase().includes(exp.toLowerCase())));
218
+ });
219
+ for (const kb of relevantKBs){
220
+ kb.entries.push(entry);
221
+ kb.metadata.lastUpdated = new Date();
222
+ if (!kb.metadata.contributors.includes(entry.agentId)) {
223
+ kb.metadata.contributors.push(entry.agentId);
224
+ }
225
+ this.logger.debug(`Updated knowledge base ${kb.id} with entry ${entry.id}`);
226
+ }
298
227
  }
299
- async storeMetrics(metricsId, metrics) {
300
- const key = `metrics:${metricsId}`;
301
- await this.store(key, metrics, {
302
- namespace: SWARM_NAMESPACES.METRICS,
303
- ttl: 86400 * 7,
304
- tags: [
305
- 'metrics',
306
- metrics.type
307
- ],
308
- metadata: {
309
- swarmId: this.swarmId,
310
- agentId: metrics.agentId,
311
- timestamp: new Date().toISOString()
228
+ async searchKnowledge(query, domain, expertise) {
229
+ const allEntries = [];
230
+ for (const kb of this.knowledgeBases.values()){
231
+ if (domain && kb.metadata.domain !== domain) continue;
232
+ if (expertise && !expertise.some((exp)=>kb.metadata.expertise.includes(exp))) {
233
+ continue;
312
234
  }
235
+ allEntries.push(...kb.entries);
236
+ }
237
+ const queryLower = query.toLowerCase();
238
+ const results = allEntries.filter((entry)=>{
239
+ const contentStr = JSON.stringify(entry.content).toLowerCase();
240
+ return contentStr.includes(queryLower);
313
241
  });
314
- this.emit('swarm:metricsStored', {
315
- metricsId,
316
- type: metrics.type
317
- });
318
- return {
319
- metricsId,
320
- stored: true
321
- };
242
+ return results.slice(0, 50);
322
243
  }
323
- async getSwarmStats() {
324
- const baseStats = await this.getStats();
325
- const agentCount = await this._countNamespace(SWARM_NAMESPACES.AGENTS);
326
- const taskCount = await this._countNamespace(SWARM_NAMESPACES.TASKS);
327
- const patternCount = await this._countNamespace(SWARM_NAMESPACES.PATTERNS);
328
- const activeAgents = Array.from(this.agentCache.values()).filter((agent)=>agent.status === 'active' || agent.status === 'busy').length;
329
- const tasks = Array.from(this.taskCache.values());
330
- const taskStats = {
331
- total: tasks.length,
332
- pending: tasks.filter((t)=>t.status === 'pending').length,
333
- inProgress: tasks.filter((t)=>t.status === 'in_progress').length,
334
- completed: tasks.filter((t)=>t.status === 'completed').length,
335
- failed: tasks.filter((t)=>t.status === 'failed').length
336
- };
244
+ async getAgentMemorySnapshot(agentId) {
245
+ const agentEntryIds = this.agentMemories.get(agentId) || new Set();
246
+ const agentEntries = Array.from(agentEntryIds).map((id)=>this.entries.get(id)).filter(Boolean);
247
+ const recentEntries = agentEntries.sort((a, b)=>b.timestamp.getTime() - a.timestamp.getTime()).slice(0, 10);
248
+ const knowledgeContributions = agentEntries.filter((e)=>e.type === 'knowledge').length;
249
+ const sharedEntries = agentEntries.filter((e)=>e.metadata.shareLevel === 'public' || e.metadata.shareLevel === 'team').length;
337
250
  return {
338
- ...baseStats,
339
- swarm: {
340
- swarmId: this.swarmId,
341
- agents: {
342
- total: agentCount,
343
- active: activeAgents,
344
- cached: this.agentCache.size
345
- },
346
- tasks: taskStats,
347
- patterns: {
348
- total: patternCount,
349
- cached: this.patternCache.size
350
- },
351
- namespaces: Object.values(SWARM_NAMESPACES)
352
- }
251
+ totalEntries: agentEntries.length,
252
+ recentEntries,
253
+ knowledgeContributions,
254
+ sharedEntries
353
255
  };
354
256
  }
355
- async cleanupSwarmData(options = {}) {
356
- const { maxAge = 86400 * 7, keepPatterns = true, keepConsensus = true } = options;
357
- const cutoffTime = Date.now() - maxAge * 1000;
358
- let cleaned = 0;
359
- const comms = await this.list(SWARM_NAMESPACES.COMMUNICATIONS);
360
- for (const comm of comms){
361
- if (new Date(comm.value.timestamp).getTime() < cutoffTime) {
362
- await this.delete(comm.key, SWARM_NAMESPACES.COMMUNICATIONS);
363
- cleaned++;
257
+ async loadMemoryState() {
258
+ try {
259
+ const entriesFile = path.join(this.config.persistencePath, 'entries.json');
260
+ try {
261
+ const entriesData = await fs.readFile(entriesFile, 'utf-8');
262
+ const entriesArray = JSON.parse(entriesData);
263
+ for (const entry of entriesArray){
264
+ this.entries.set(entry.id, {
265
+ ...entry,
266
+ timestamp: new Date(entry.timestamp)
267
+ });
268
+ if (!this.agentMemories.has(entry.agentId)) {
269
+ this.agentMemories.set(entry.agentId, new Set());
270
+ }
271
+ this.agentMemories.get(entry.agentId).add(entry.id);
272
+ }
273
+ this.logger.info(`Loaded ${entriesArray.length} memory entries`);
274
+ } catch (error) {
275
+ this.logger.warn('No existing memory entries found');
364
276
  }
365
- }
366
- const tasks = await this.list(SWARM_NAMESPACES.TASKS);
367
- for (const task of tasks){
368
- if (task.value.status === 'completed' && new Date(task.value.completedAt).getTime() < cutoffTime) {
369
- await this.delete(task.key, SWARM_NAMESPACES.TASKS);
370
- this.taskCache.delete(task.value.id);
371
- cleaned++;
277
+ const kbFile = path.join(this.config.persistencePath, 'knowledge-bases.json');
278
+ try {
279
+ const kbData = await fs.readFile(kbFile, 'utf-8');
280
+ const kbArray = JSON.parse(kbData);
281
+ for (const kb of kbArray){
282
+ this.knowledgeBases.set(kb.id, {
283
+ ...kb,
284
+ metadata: {
285
+ ...kb.metadata,
286
+ lastUpdated: new Date(kb.metadata.lastUpdated)
287
+ },
288
+ entries: kb.entries.map((e)=>({
289
+ ...e,
290
+ timestamp: new Date(e.timestamp)
291
+ }))
292
+ });
293
+ }
294
+ this.logger.info(`Loaded ${kbArray.length} knowledge bases`);
295
+ } catch (error) {
296
+ this.logger.warn('No existing knowledge bases found');
372
297
  }
298
+ } catch (error) {
299
+ this.logger.error('Error loading memory state:', error);
300
+ }
301
+ }
302
+ async saveMemoryState() {
303
+ try {
304
+ const entriesArray = Array.from(this.entries.values());
305
+ const entriesFile = path.join(this.config.persistencePath, 'entries.json');
306
+ await fs.writeFile(entriesFile, JSON.stringify(entriesArray, null, 2));
307
+ const kbArray = Array.from(this.knowledgeBases.values());
308
+ const kbFile = path.join(this.config.persistencePath, 'knowledge-bases.json');
309
+ await fs.writeFile(kbFile, JSON.stringify(kbArray, null, 2));
310
+ this.logger.debug('Saved memory state to disk');
311
+ } catch (error) {
312
+ this.logger.error('Error saving memory state:', error);
313
+ }
314
+ }
315
+ async syncMemoryState() {
316
+ try {
317
+ await this.saveMemoryState();
318
+ this.emit('memory:synced');
319
+ } catch (error) {
320
+ this.logger.error('Error syncing memory state:', error);
373
321
  }
374
- const metrics = await this.list(SWARM_NAMESPACES.METRICS);
375
- for (const metric of metrics){
376
- if (new Date(metric.createdAt).getTime() < cutoffTime) {
377
- await this.delete(metric.key, SWARM_NAMESPACES.METRICS);
378
- cleaned++;
322
+ }
323
+ async enforceMemoryLimits() {
324
+ if (this.entries.size <= this.config.maxEntries) return;
325
+ this.logger.info('Enforcing memory limits...');
326
+ const entries = Array.from(this.entries.values()).filter((e)=>(e.metadata.priority || 1) <= 1).sort((a, b)=>a.timestamp.getTime() - b.timestamp.getTime());
327
+ const toRemove = entries.slice(0, this.entries.size - this.config.maxEntries);
328
+ for (const entry of toRemove){
329
+ this.entries.delete(entry.id);
330
+ const agentEntries = this.agentMemories.get(entry.agentId);
331
+ if (agentEntries) {
332
+ agentEntries.delete(entry.id);
379
333
  }
334
+ this.logger.debug(`Removed old memory entry: ${entry.id}`);
380
335
  }
381
- this.emit('swarm:cleanup', {
382
- cleaned,
383
- maxAge
384
- });
336
+ this.emit('memory:cleaned', toRemove.length);
337
+ }
338
+ getMemoryStats() {
339
+ const entries = Array.from(this.entries.values());
340
+ const entriesByType = {};
341
+ const entriesByAgent = {};
342
+ for (const entry of entries){
343
+ entriesByType[entry.type] = (entriesByType[entry.type] || 0) + 1;
344
+ entriesByAgent[entry.agentId] = (entriesByAgent[entry.agentId] || 0) + 1;
345
+ }
346
+ const memoryUsage = JSON.stringify(entries).length;
385
347
  return {
386
- cleaned
348
+ totalEntries: entries.length,
349
+ entriesByType,
350
+ entriesByAgent,
351
+ knowledgeBases: this.knowledgeBases.size,
352
+ memoryUsage
387
353
  };
388
354
  }
389
- async exportSwarmState() {
390
- const agents = await this.listAgents();
391
- const tasks = Array.from(this.taskCache.values());
392
- const patterns = await this.list(SWARM_NAMESPACES.PATTERNS);
355
+ async exportMemory(agentId) {
356
+ const entries = agentId ? await this.recall({
357
+ agentId
358
+ }) : Array.from(this.entries.values());
393
359
  return {
394
- swarmId: this.swarmId,
395
- exportedAt: new Date().toISOString(),
396
- agents: agents,
397
- tasks: tasks,
398
- patterns: patterns.map((p)=>p.value),
399
- statistics: await this.getSwarmStats()
360
+ entries,
361
+ knowledgeBases: agentId ? Array.from(this.knowledgeBases.values()).filter((kb)=>kb.metadata.contributors.includes(agentId)) : Array.from(this.knowledgeBases.values()),
362
+ exportedAt: new Date(),
363
+ stats: this.getMemoryStats()
400
364
  };
401
365
  }
402
- async importSwarmState(state) {
403
- let imported = {
404
- agents: 0,
405
- tasks: 0,
406
- patterns: 0
407
- };
408
- if (state.agents) {
409
- for (const agent of state.agents){
410
- await this.storeAgent(agent.id, agent);
411
- imported.agents++;
366
+ async clearMemory(agentId) {
367
+ if (agentId) {
368
+ const entryIds = this.agentMemories.get(agentId) || new Set();
369
+ for (const entryId of entryIds){
370
+ this.entries.delete(entryId);
412
371
  }
372
+ this.agentMemories.delete(agentId);
373
+ this.logger.info(`Cleared memory for agent ${agentId}`);
374
+ } else {
375
+ this.entries.clear();
376
+ this.agentMemories.clear();
377
+ this.knowledgeBases.clear();
378
+ this.logger.info('Cleared all swarm memory');
413
379
  }
414
- if (state.tasks) {
415
- for (const task of state.tasks){
416
- await this.storeTask(task.id, task);
417
- imported.tasks++;
418
- }
419
- }
420
- if (state.patterns) {
421
- for (const pattern of state.patterns){
422
- await this.storePattern(pattern.id, pattern);
423
- imported.patterns++;
424
- }
425
- }
426
- this.emit('swarm:imported', imported);
427
- return imported;
428
- }
429
- async _initializeSwarmNamespaces() {
430
- await this.store('swarm:metadata', {
431
- swarmId: this.swarmId,
432
- createdAt: new Date().toISOString(),
433
- version: '1.0.0',
434
- namespaces: Object.values(SWARM_NAMESPACES)
435
- }, {
436
- namespace: 'swarm:system'
380
+ this.emit('memory:cleared', {
381
+ agentId
437
382
  });
438
383
  }
439
- async _loadSwarmState() {
440
- const agents = await this.list(SWARM_NAMESPACES.AGENTS, {
441
- limit: 100
442
- });
443
- for (const entry of agents){
444
- if (entry.value.status === 'active' || entry.value.status === 'busy') {
445
- this.agentCache.set(entry.value.id, entry.value);
446
- }
447
- }
448
- const tasks = await this.search({
449
- namespace: SWARM_NAMESPACES.TASKS,
384
+ async store(key, value) {
385
+ const parts = key.split('/');
386
+ const type = parts[0] || 'state';
387
+ const agentId = parts[1] || 'system';
388
+ await this.remember(agentId, type, value, {
450
389
  tags: [
451
- 'in_progress'
452
- ],
453
- limit: 100
454
- });
455
- for (const entry of tasks){
456
- this.taskCache.set(entry.value.id, entry.value);
457
- }
458
- const patterns = await this.list(SWARM_NAMESPACES.PATTERNS, {
459
- limit: 50
390
+ parts[0],
391
+ parts[1]
392
+ ].filter(Boolean),
393
+ shareLevel: 'team'
460
394
  });
461
- for (const entry of patterns){
462
- if (entry.value.confidence > 0.7 || entry.value.successRate > 0.8) {
463
- this.patternCache.set(entry.value.id, entry.value);
395
+ }
396
+ async search(pattern, limit = 10) {
397
+ const results = [];
398
+ for (const entry of this.entries.values()){
399
+ const entryString = JSON.stringify(entry);
400
+ if (entryString.includes(pattern.replace('*', ''))) {
401
+ results.push(entry.content);
402
+ if (results.length >= limit) break;
464
403
  }
465
404
  }
405
+ return results;
466
406
  }
467
- async _countNamespace(namespace) {
468
- const stats = await this.getStats();
469
- return stats.namespaces[namespace]?.count || 0;
470
- }
471
- }
472
- export function createSwarmMemory(options = {}) {
473
- return new SwarmMemory(options);
474
407
  }
475
- export default SwarmMemory;
476
408
 
477
409
  //# sourceMappingURL=swarm-memory.js.map