claude-flow 2.7.43 → 2.7.44
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/bin/claude-flow +1 -1
- package/dist/src/cli/help-formatter.js +0 -5
- package/dist/src/cli/simple-commands/config.js +257 -115
- package/dist/src/cli/simple-commands/config.js.map +1 -1
- package/dist/src/cli/validation-helper.js.map +1 -1
- package/dist/src/core/version.js +2 -2
- package/dist/src/core/version.js.map +1 -1
- package/dist/src/memory/in-memory-store.js +1 -0
- package/dist/src/memory/in-memory-store.js.map +1 -1
- package/dist/src/memory/swarm-memory.js +348 -416
- package/dist/src/memory/swarm-memory.js.map +1 -1
- package/dist/src/utils/metrics-reader.js +0 -10
- package/package.json +1 -1
- package/src/memory/in-memory-store.js +2 -0
|
@@ -1,477 +1,409 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
await this.
|
|
28
|
-
this.
|
|
29
|
-
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
await this.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
48
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
100
|
-
|
|
96
|
+
type: 'swarm-memory',
|
|
97
|
+
agentId,
|
|
98
|
+
entryType: type,
|
|
99
|
+
shareLevel: entry.metadata.shareLevel
|
|
101
100
|
}
|
|
102
101
|
});
|
|
103
|
-
this.
|
|
104
|
-
this.emit('
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
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
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
if (result) {
|
|
121
|
-
task.result = result;
|
|
115
|
+
if (query.type) {
|
|
116
|
+
results = results.filter((e)=>e.type === query.type);
|
|
122
117
|
}
|
|
123
|
-
if (
|
|
124
|
-
|
|
118
|
+
if (query.taskId) {
|
|
119
|
+
results = results.filter((e)=>e.metadata.taskId === query.taskId);
|
|
125
120
|
}
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
142
|
-
|
|
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
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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.
|
|
234
|
-
|
|
235
|
-
|
|
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
|
|
243
|
-
const
|
|
244
|
-
if (!
|
|
245
|
-
throw new Error(
|
|
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
|
-
|
|
248
|
-
|
|
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
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
-
|
|
288
|
-
|
|
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
|
|
297
|
-
|
|
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
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
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
|
-
|
|
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
|
|
324
|
-
const
|
|
325
|
-
const
|
|
326
|
-
const
|
|
327
|
-
const
|
|
328
|
-
const
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
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
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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('
|
|
382
|
-
|
|
383
|
-
|
|
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
|
-
|
|
348
|
+
totalEntries: entries.length,
|
|
349
|
+
entriesByType,
|
|
350
|
+
entriesByAgent,
|
|
351
|
+
knowledgeBases: this.knowledgeBases.size,
|
|
352
|
+
memoryUsage
|
|
387
353
|
};
|
|
388
354
|
}
|
|
389
|
-
async
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
355
|
+
async exportMemory(agentId) {
|
|
356
|
+
const entries = agentId ? await this.recall({
|
|
357
|
+
agentId
|
|
358
|
+
}) : Array.from(this.entries.values());
|
|
393
359
|
return {
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
415
|
-
|
|
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
|
|
440
|
-
const
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
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
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
462
|
-
|
|
463
|
-
|
|
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
|