@lov3kaizen/agentsea-memory 0.5.1

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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +450 -0
  3. package/dist/chunk-GACX3FPR.js +1402 -0
  4. package/dist/chunk-M44NB53O.js +1226 -0
  5. package/dist/chunk-MQDWBPZU.js +972 -0
  6. package/dist/chunk-TPC7MYWK.js +1495 -0
  7. package/dist/chunk-XD2CQGSD.js +1540 -0
  8. package/dist/chunk-YI7RPDEV.js +1215 -0
  9. package/dist/core.types-lkxKv-bW.d.cts +242 -0
  10. package/dist/core.types-lkxKv-bW.d.ts +242 -0
  11. package/dist/debug/index.cjs +1248 -0
  12. package/dist/debug/index.d.cts +3 -0
  13. package/dist/debug/index.d.ts +3 -0
  14. package/dist/debug/index.js +20 -0
  15. package/dist/index-7SsAJ4et.d.ts +525 -0
  16. package/dist/index-BGxYqpFb.d.cts +601 -0
  17. package/dist/index-BX62efZu.d.ts +565 -0
  18. package/dist/index-Bbc3COw0.d.cts +748 -0
  19. package/dist/index-Bczz1Eyk.d.ts +637 -0
  20. package/dist/index-C7pEiT8L.d.cts +637 -0
  21. package/dist/index-CHetLTb0.d.ts +389 -0
  22. package/dist/index-CloeiFyx.d.ts +748 -0
  23. package/dist/index-DNOhq-3y.d.cts +525 -0
  24. package/dist/index-Da-M8FOV.d.cts +389 -0
  25. package/dist/index-Dy8UjRFz.d.cts +565 -0
  26. package/dist/index-aVcITW0B.d.ts +601 -0
  27. package/dist/index.cjs +8554 -0
  28. package/dist/index.d.cts +293 -0
  29. package/dist/index.d.ts +293 -0
  30. package/dist/index.js +742 -0
  31. package/dist/processing/index.cjs +1575 -0
  32. package/dist/processing/index.d.cts +2 -0
  33. package/dist/processing/index.d.ts +2 -0
  34. package/dist/processing/index.js +24 -0
  35. package/dist/retrieval/index.cjs +1262 -0
  36. package/dist/retrieval/index.d.cts +2 -0
  37. package/dist/retrieval/index.d.ts +2 -0
  38. package/dist/retrieval/index.js +26 -0
  39. package/dist/sharing/index.cjs +1003 -0
  40. package/dist/sharing/index.d.cts +3 -0
  41. package/dist/sharing/index.d.ts +3 -0
  42. package/dist/sharing/index.js +16 -0
  43. package/dist/stores/index.cjs +1445 -0
  44. package/dist/stores/index.d.cts +2 -0
  45. package/dist/stores/index.d.ts +2 -0
  46. package/dist/stores/index.js +20 -0
  47. package/dist/structures/index.cjs +1530 -0
  48. package/dist/structures/index.d.cts +3 -0
  49. package/dist/structures/index.d.ts +3 -0
  50. package/dist/structures/index.js +24 -0
  51. package/package.json +141 -0
@@ -0,0 +1,1003 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/sharing/index.ts
21
+ var sharing_exports = {};
22
+ __export(sharing_exports, {
23
+ AccessControl: () => AccessControl,
24
+ NamespaceManager: () => NamespaceManager,
25
+ SharedMemory: () => SharedMemory,
26
+ createAccessControl: () => createAccessControl,
27
+ createNamespaceManager: () => createNamespaceManager,
28
+ createSharedMemory: () => createSharedMemory
29
+ });
30
+ module.exports = __toCommonJS(sharing_exports);
31
+
32
+ // src/sharing/SharedMemory.ts
33
+ var import_eventemitter3 = require("eventemitter3");
34
+ var SharedMemory = class extends import_eventemitter3.EventEmitter {
35
+ store;
36
+ config;
37
+ sharedState = /* @__PURE__ */ new Map();
38
+ agentStates = /* @__PURE__ */ new Map();
39
+ subscriptions = /* @__PURE__ */ new Map();
40
+ // key -> agent IDs
41
+ lockManager = /* @__PURE__ */ new Map();
42
+ constructor(store, config = {}) {
43
+ super();
44
+ this.store = store;
45
+ this.config = {
46
+ conflictResolution: config.conflictResolution ?? "last-write-wins",
47
+ syncInterval: config.syncInterval ?? 5e3,
48
+ enableLocking: config.enableLocking ?? true,
49
+ lockTimeout: config.lockTimeout ?? 3e4,
50
+ maxSharedEntries: config.maxSharedEntries ?? 1e3
51
+ };
52
+ }
53
+ /**
54
+ * Set a shared value
55
+ */
56
+ async set(agentId, key, value) {
57
+ if (this.config.enableLocking && this.isLocked(key) && !this.hasLock(key, agentId)) {
58
+ return false;
59
+ }
60
+ const existing = this.sharedState.get(key);
61
+ if (existing && existing.writtenBy !== agentId) {
62
+ const resolved = this.resolveConflict(key, existing, { agentId, value });
63
+ if (!resolved) {
64
+ this.emit("conflict", key, [existing.writtenBy, agentId]);
65
+ return false;
66
+ }
67
+ }
68
+ const sharedValue = {
69
+ value,
70
+ writtenBy: agentId,
71
+ writtenAt: Date.now(),
72
+ version: (existing?.version ?? 0) + 1,
73
+ readers: existing?.readers ?? /* @__PURE__ */ new Set()
74
+ };
75
+ this.sharedState.set(key, sharedValue);
76
+ await this.persistSharedValue(key, sharedValue);
77
+ this.emit("write", agentId, key, value);
78
+ this.notifySubscribers(key, agentId, value);
79
+ return true;
80
+ }
81
+ /**
82
+ * Get a shared value
83
+ */
84
+ async get(agentId, key) {
85
+ const shared = this.sharedState.get(key);
86
+ if (!shared) {
87
+ const loaded = await this.loadSharedValue(key);
88
+ if (!loaded) return void 0;
89
+ this.sharedState.set(key, loaded);
90
+ return loaded.value;
91
+ }
92
+ shared.readers.add(agentId);
93
+ this.emit("read", agentId, key);
94
+ return shared.value;
95
+ }
96
+ /**
97
+ * Delete a shared value
98
+ */
99
+ async delete(agentId, key) {
100
+ if (this.config.enableLocking && this.isLocked(key) && !this.hasLock(key, agentId)) {
101
+ return false;
102
+ }
103
+ const existed = this.sharedState.delete(key);
104
+ if (existed) {
105
+ await this.store.delete(`shared:${key}`);
106
+ this.emit("delete", agentId, key);
107
+ }
108
+ return existed;
109
+ }
110
+ /**
111
+ * Set agent-specific state (not shared)
112
+ */
113
+ setAgentState(agentId, key, value) {
114
+ if (!this.agentStates.has(agentId)) {
115
+ this.agentStates.set(agentId, /* @__PURE__ */ new Map());
116
+ }
117
+ this.agentStates.get(agentId).set(key, value);
118
+ }
119
+ /**
120
+ * Get agent-specific state
121
+ */
122
+ getAgentState(agentId, key) {
123
+ return this.agentStates.get(agentId)?.get(key);
124
+ }
125
+ /**
126
+ * Get all agent state
127
+ */
128
+ getAllAgentState(agentId) {
129
+ return new Map(this.agentStates.get(agentId) ?? []);
130
+ }
131
+ /**
132
+ * Subscribe to changes on a key
133
+ */
134
+ subscribe(agentId, key) {
135
+ if (!this.subscriptions.has(key)) {
136
+ this.subscriptions.set(key, /* @__PURE__ */ new Set());
137
+ }
138
+ this.subscriptions.get(key).add(agentId);
139
+ }
140
+ /**
141
+ * Unsubscribe from changes
142
+ */
143
+ unsubscribe(agentId, key) {
144
+ this.subscriptions.get(key)?.delete(agentId);
145
+ }
146
+ /**
147
+ * Acquire a lock on a key
148
+ */
149
+ acquireLock(agentId, key) {
150
+ if (!this.config.enableLocking) return true;
151
+ const lock = this.lockManager.get(key);
152
+ if (lock && lock.expiresAt > Date.now() && lock.agentId !== agentId) {
153
+ return false;
154
+ }
155
+ this.lockManager.set(key, {
156
+ agentId,
157
+ expiresAt: Date.now() + this.config.lockTimeout
158
+ });
159
+ return true;
160
+ }
161
+ /**
162
+ * Release a lock
163
+ */
164
+ releaseLock(agentId, key) {
165
+ const lock = this.lockManager.get(key);
166
+ if (lock?.agentId === agentId) {
167
+ this.lockManager.delete(key);
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
+ /**
173
+ * Check if key is locked
174
+ */
175
+ isLocked(key) {
176
+ const lock = this.lockManager.get(key);
177
+ return lock !== void 0 && lock.expiresAt > Date.now();
178
+ }
179
+ /**
180
+ * Check if agent has lock
181
+ */
182
+ hasLock(key, agentId) {
183
+ const lock = this.lockManager.get(key);
184
+ return lock?.agentId === agentId && lock.expiresAt > Date.now();
185
+ }
186
+ /**
187
+ * Share memories from one agent to shared space
188
+ */
189
+ async shareMemories(agentId, entries) {
190
+ let added = 0;
191
+ let updated = 0;
192
+ let conflicts = 0;
193
+ for (const entry of entries) {
194
+ const key = `memory:${entry.id}`;
195
+ const existing = this.sharedState.get(key);
196
+ if (existing) {
197
+ if (existing.writtenBy !== agentId) {
198
+ if (this.config.conflictResolution === "last-write-wins") {
199
+ await this.set(agentId, key, entry);
200
+ updated++;
201
+ } else {
202
+ conflicts++;
203
+ }
204
+ } else {
205
+ await this.set(agentId, key, entry);
206
+ updated++;
207
+ }
208
+ } else {
209
+ await this.set(agentId, key, entry);
210
+ added++;
211
+ }
212
+ }
213
+ this.emit("sync", agentId, entries);
214
+ return {
215
+ added,
216
+ updated,
217
+ conflicts,
218
+ timestamp: Date.now()
219
+ };
220
+ }
221
+ /**
222
+ * Get shared memories
223
+ */
224
+ getSharedMemories(_agentId) {
225
+ const memories = [];
226
+ for (const [key, shared] of this.sharedState) {
227
+ if (key.startsWith("memory:")) {
228
+ const entry = shared.value;
229
+ memories.push(entry);
230
+ }
231
+ }
232
+ return memories;
233
+ }
234
+ /**
235
+ * Sync with store
236
+ */
237
+ async sync() {
238
+ for (const [key, value] of this.sharedState) {
239
+ await this.persistSharedValue(key, value);
240
+ }
241
+ }
242
+ /**
243
+ * Get all shared keys
244
+ */
245
+ getSharedKeys() {
246
+ return Array.from(this.sharedState.keys());
247
+ }
248
+ /**
249
+ * Get metadata for a shared value
250
+ */
251
+ getMetadata(key) {
252
+ const shared = this.sharedState.get(key);
253
+ if (!shared) return void 0;
254
+ return {
255
+ writtenBy: shared.writtenBy,
256
+ writtenAt: shared.writtenAt,
257
+ version: shared.version,
258
+ readers: shared.readers
259
+ };
260
+ }
261
+ /**
262
+ * Resolve conflict between values
263
+ */
264
+ resolveConflict(key, existing, incoming) {
265
+ switch (this.config.conflictResolution) {
266
+ case "last-write-wins":
267
+ return true;
268
+ case "first-write-wins":
269
+ return false;
270
+ case "merge":
271
+ if (typeof existing.value === "object" && typeof incoming.value === "object") {
272
+ this.sharedState.set(key, {
273
+ ...existing,
274
+ value: {
275
+ ...existing.value,
276
+ ...incoming.value
277
+ },
278
+ writtenBy: incoming.agentId,
279
+ writtenAt: Date.now(),
280
+ version: existing.version + 1
281
+ });
282
+ return true;
283
+ }
284
+ return true;
285
+ // Fall back to last-write-wins for non-objects
286
+ default:
287
+ return true;
288
+ }
289
+ }
290
+ /**
291
+ * Notify subscribers of changes
292
+ */
293
+ notifySubscribers(key, writerId, value) {
294
+ const subscribers = this.subscriptions.get(key);
295
+ if (!subscribers) return;
296
+ for (const agentId of subscribers) {
297
+ if (agentId !== writerId) {
298
+ this.emit("write", writerId, key, value);
299
+ }
300
+ }
301
+ }
302
+ /**
303
+ * Persist shared value to store
304
+ */
305
+ async persistSharedValue(key, value) {
306
+ await this.store.add({
307
+ id: `shared:${key}`,
308
+ content: JSON.stringify(value),
309
+ type: "context",
310
+ importance: 0.5,
311
+ metadata: {
312
+ source: "agent",
313
+ confidence: 1,
314
+ sharedKey: key,
315
+ writtenBy: value.writtenBy,
316
+ version: value.version
317
+ },
318
+ timestamp: value.writtenAt,
319
+ accessCount: 0,
320
+ createdAt: value.writtenAt,
321
+ updatedAt: value.writtenAt
322
+ });
323
+ }
324
+ /**
325
+ * Load shared value from store
326
+ */
327
+ async loadSharedValue(key) {
328
+ const entry = await this.store.get(`shared:${key}`);
329
+ if (!entry) return null;
330
+ try {
331
+ const data = JSON.parse(entry.content);
332
+ return {
333
+ ...data,
334
+ readers: new Set(data.readers ?? [])
335
+ };
336
+ } catch {
337
+ return null;
338
+ }
339
+ }
340
+ /**
341
+ * Get statistics
342
+ */
343
+ getStats() {
344
+ let totalSubscriptions = 0;
345
+ for (const subs of this.subscriptions.values()) {
346
+ totalSubscriptions += subs.size;
347
+ }
348
+ return {
349
+ sharedEntries: this.sharedState.size,
350
+ agentCount: this.agentStates.size,
351
+ activeLocks: Array.from(this.lockManager.values()).filter(
352
+ (l) => l.expiresAt > Date.now()
353
+ ).length,
354
+ totalSubscriptions
355
+ };
356
+ }
357
+ };
358
+ function createSharedMemory(store, config) {
359
+ return new SharedMemory(store, config);
360
+ }
361
+
362
+ // src/sharing/Namespaces.ts
363
+ var import_eventemitter32 = require("eventemitter3");
364
+ var NamespaceManager = class extends import_eventemitter32.EventEmitter {
365
+ store;
366
+ namespaces = /* @__PURE__ */ new Map();
367
+ defaultNamespace = "default";
368
+ constructor(store, _config) {
369
+ super();
370
+ this.store = store;
371
+ this.createNamespace("default", {
372
+ description: "Default namespace",
373
+ settings: { accessLevel: "public" }
374
+ });
375
+ }
376
+ /**
377
+ * Create a new namespace
378
+ */
379
+ createNamespace(name, options = {}) {
380
+ if (this.namespaces.has(name)) {
381
+ throw new Error(`Namespace "${name}" already exists`);
382
+ }
383
+ const metadata = {
384
+ name,
385
+ description: options.description,
386
+ owner: options.owner,
387
+ createdAt: Date.now(),
388
+ updatedAt: Date.now(),
389
+ entryCount: 0,
390
+ tags: options.tags,
391
+ settings: {
392
+ accessLevel: "private",
393
+ ...options.settings
394
+ }
395
+ };
396
+ this.namespaces.set(name, metadata);
397
+ this.emit("created", metadata);
398
+ return metadata;
399
+ }
400
+ /**
401
+ * Delete a namespace
402
+ */
403
+ async deleteNamespace(name, deleteEntries = false) {
404
+ if (name === "default") {
405
+ throw new Error("Cannot delete default namespace");
406
+ }
407
+ if (!this.namespaces.has(name)) {
408
+ return false;
409
+ }
410
+ if (deleteEntries) {
411
+ await this.store.clear({ namespace: name });
412
+ }
413
+ this.namespaces.delete(name);
414
+ this.emit("deleted", name);
415
+ return true;
416
+ }
417
+ /**
418
+ * Get namespace metadata
419
+ */
420
+ getNamespace(name) {
421
+ return this.namespaces.get(name);
422
+ }
423
+ /**
424
+ * List all namespaces
425
+ */
426
+ listNamespaces() {
427
+ return Array.from(this.namespaces.values());
428
+ }
429
+ /**
430
+ * Update namespace settings
431
+ */
432
+ updateNamespace(name, updates) {
433
+ const existing = this.namespaces.get(name);
434
+ if (!existing) return null;
435
+ const updated = {
436
+ ...existing,
437
+ ...updates,
438
+ settings: {
439
+ ...existing.settings,
440
+ ...updates.settings
441
+ },
442
+ updatedAt: Date.now()
443
+ };
444
+ this.namespaces.set(name, updated);
445
+ this.emit("updated", updated);
446
+ return updated;
447
+ }
448
+ /**
449
+ * Check if agent can access namespace
450
+ */
451
+ canAccess(name, agentId, action = "read") {
452
+ const namespace = this.namespaces.get(name);
453
+ if (!namespace) return false;
454
+ const { settings } = namespace;
455
+ if (settings.accessLevel === "public") {
456
+ return action === "read" || !settings.readOnly;
457
+ }
458
+ if (settings.accessLevel === "private") {
459
+ return namespace.owner === agentId;
460
+ }
461
+ if (settings.accessLevel === "restricted") {
462
+ const isAllowed = settings.allowedAgents?.includes(agentId) ?? false;
463
+ if (!isAllowed) {
464
+ this.emit("accessDenied", name, agentId, action);
465
+ return false;
466
+ }
467
+ return action === "read" || !settings.readOnly;
468
+ }
469
+ return false;
470
+ }
471
+ /**
472
+ * Add entry to namespace
473
+ */
474
+ async addEntry(namespace, entry, agentId) {
475
+ if (!this.canAccess(namespace, agentId, "write")) {
476
+ return null;
477
+ }
478
+ const ns = this.namespaces.get(namespace);
479
+ if (!ns) return null;
480
+ if (ns.settings.maxEntries && ns.entryCount >= ns.settings.maxEntries) {
481
+ return null;
482
+ }
483
+ const fullEntry = {
484
+ ...entry,
485
+ metadata: {
486
+ source: entry.metadata?.source ?? "explicit",
487
+ confidence: entry.metadata?.confidence ?? 1,
488
+ ...entry.metadata,
489
+ namespace
490
+ },
491
+ expiresAt: ns.settings.ttl ? Date.now() + ns.settings.ttl : entry.expiresAt
492
+ };
493
+ await this.store.add(fullEntry);
494
+ ns.entryCount++;
495
+ ns.updatedAt = Date.now();
496
+ this.emit("entryAdded", namespace, fullEntry);
497
+ return fullEntry.id;
498
+ }
499
+ /**
500
+ * Query entries in namespace
501
+ */
502
+ async queryEntries(namespace, agentId, options) {
503
+ if (!this.canAccess(namespace, agentId, "read")) {
504
+ return [];
505
+ }
506
+ const { entries } = await this.store.query({
507
+ namespace,
508
+ query: options?.query,
509
+ limit: options?.limit,
510
+ types: options?.types
511
+ });
512
+ return entries;
513
+ }
514
+ /**
515
+ * Delete entry from namespace
516
+ */
517
+ async deleteEntry(namespace, entryId, agentId) {
518
+ if (!this.canAccess(namespace, agentId, "write")) {
519
+ return false;
520
+ }
521
+ const result = await this.store.delete(entryId);
522
+ if (result) {
523
+ const ns = this.namespaces.get(namespace);
524
+ if (ns) {
525
+ ns.entryCount = Math.max(0, ns.entryCount - 1);
526
+ ns.updatedAt = Date.now();
527
+ }
528
+ }
529
+ return result;
530
+ }
531
+ /**
532
+ * Move entries between namespaces
533
+ */
534
+ async moveEntries(fromNamespace, toNamespace, entryIds, agentId) {
535
+ if (!this.canAccess(fromNamespace, agentId, "write")) return 0;
536
+ if (!this.canAccess(toNamespace, agentId, "write")) return 0;
537
+ let moved = 0;
538
+ for (const id of entryIds) {
539
+ const entry = await this.store.get(id);
540
+ if (entry && entry.metadata.namespace === fromNamespace) {
541
+ await this.store.update(id, {
542
+ metadata: { ...entry.metadata, namespace: toNamespace }
543
+ });
544
+ moved++;
545
+ }
546
+ }
547
+ const fromNs = this.namespaces.get(fromNamespace);
548
+ const toNs = this.namespaces.get(toNamespace);
549
+ if (fromNs) fromNs.entryCount -= moved;
550
+ if (toNs) toNs.entryCount += moved;
551
+ return moved;
552
+ }
553
+ /**
554
+ * Copy entries between namespaces
555
+ */
556
+ async copyEntries(fromNamespace, toNamespace, entryIds, agentId) {
557
+ if (!this.canAccess(fromNamespace, agentId, "read")) return 0;
558
+ if (!this.canAccess(toNamespace, agentId, "write")) return 0;
559
+ let copied = 0;
560
+ for (const id of entryIds) {
561
+ const entry = await this.store.get(id);
562
+ if (entry && entry.metadata.namespace === fromNamespace) {
563
+ const newEntry = {
564
+ ...entry,
565
+ id: `${entry.id}-copy-${Date.now()}`,
566
+ metadata: { ...entry.metadata, namespace: toNamespace },
567
+ createdAt: Date.now(),
568
+ updatedAt: Date.now()
569
+ };
570
+ await this.store.add(newEntry);
571
+ copied++;
572
+ }
573
+ }
574
+ const toNs = this.namespaces.get(toNamespace);
575
+ if (toNs) toNs.entryCount += copied;
576
+ return copied;
577
+ }
578
+ /**
579
+ * Grant access to namespace
580
+ */
581
+ grantAccess(namespace, agentId) {
582
+ const ns = this.namespaces.get(namespace);
583
+ if (!ns) return false;
584
+ if (!ns.settings.allowedAgents) {
585
+ ns.settings.allowedAgents = [];
586
+ }
587
+ if (!ns.settings.allowedAgents.includes(agentId)) {
588
+ ns.settings.allowedAgents.push(agentId);
589
+ }
590
+ return true;
591
+ }
592
+ /**
593
+ * Revoke access from namespace
594
+ */
595
+ revokeAccess(namespace, agentId) {
596
+ const ns = this.namespaces.get(namespace);
597
+ if (!ns || !ns.settings.allowedAgents) return false;
598
+ const index = ns.settings.allowedAgents.indexOf(agentId);
599
+ if (index !== -1) {
600
+ ns.settings.allowedAgents.splice(index, 1);
601
+ return true;
602
+ }
603
+ return false;
604
+ }
605
+ /**
606
+ * Set default namespace
607
+ */
608
+ setDefaultNamespace(name) {
609
+ if (!this.namespaces.has(name)) return false;
610
+ this.defaultNamespace = name;
611
+ return true;
612
+ }
613
+ /**
614
+ * Get default namespace
615
+ */
616
+ getDefaultNamespace() {
617
+ return this.defaultNamespace;
618
+ }
619
+ /**
620
+ * Get namespace statistics
621
+ */
622
+ async getNamespaceStats(name) {
623
+ if (!this.namespaces.has(name)) return null;
624
+ const { entries, total } = await this.store.query({
625
+ namespace: name,
626
+ limit: 1e4
627
+ });
628
+ const typeDistribution = {};
629
+ let oldestEntry = null;
630
+ let newestEntry = null;
631
+ let totalSize = 0;
632
+ for (const entry of entries) {
633
+ typeDistribution[entry.type] = (typeDistribution[entry.type] ?? 0) + 1;
634
+ totalSize += entry.content.length;
635
+ if (oldestEntry === null || entry.timestamp < oldestEntry) {
636
+ oldestEntry = entry.timestamp;
637
+ }
638
+ if (newestEntry === null || entry.timestamp > newestEntry) {
639
+ newestEntry = entry.timestamp;
640
+ }
641
+ }
642
+ return {
643
+ entryCount: total,
644
+ totalSize,
645
+ oldestEntry,
646
+ newestEntry,
647
+ typeDistribution
648
+ };
649
+ }
650
+ };
651
+ function createNamespaceManager(store, config) {
652
+ return new NamespaceManager(store, config);
653
+ }
654
+
655
+ // src/sharing/AccessControl.ts
656
+ var import_eventemitter33 = require("eventemitter3");
657
+ var AccessControl = class extends import_eventemitter33.EventEmitter {
658
+ config;
659
+ rules = /* @__PURE__ */ new Map();
660
+ accessLog = [];
661
+ maxLogSize = 1e3;
662
+ constructor(config = {}) {
663
+ super();
664
+ this.config = {
665
+ roles: config.roles ?? {},
666
+ defaultRole: config.defaultRole ?? "user",
667
+ adminUsers: config.adminUsers ?? [],
668
+ defaultPermission: config.defaultPermission ?? "read",
669
+ enableAuditLog: config.enableAuditLog ?? true,
670
+ strictMode: config.strictMode ?? false,
671
+ maxRulesPerAgent: config.maxRulesPerAgent ?? 100
672
+ };
673
+ if (!this.config.strictMode) {
674
+ this.addRule({
675
+ id: "default-read",
676
+ agentId: "*",
677
+ resource: "*",
678
+ permission: this.config.defaultPermission,
679
+ createdBy: "system",
680
+ createdAt: Date.now()
681
+ });
682
+ }
683
+ }
684
+ /**
685
+ * Add a permission rule
686
+ */
687
+ addRule(rule) {
688
+ if (rule.agentId !== "*") {
689
+ const agentRules = Array.from(this.rules.values()).filter(
690
+ (r) => r.agentId === rule.agentId
691
+ );
692
+ if (agentRules.length >= this.config.maxRulesPerAgent) {
693
+ return false;
694
+ }
695
+ }
696
+ this.rules.set(rule.id, rule);
697
+ this.emit("ruleAdded", rule);
698
+ return true;
699
+ }
700
+ /**
701
+ * Remove a permission rule
702
+ */
703
+ removeRule(ruleId) {
704
+ const existed = this.rules.delete(ruleId);
705
+ if (existed) {
706
+ this.emit("ruleRemoved", ruleId);
707
+ }
708
+ return existed;
709
+ }
710
+ /**
711
+ * Get rule by ID
712
+ */
713
+ getRule(ruleId) {
714
+ return this.rules.get(ruleId);
715
+ }
716
+ /**
717
+ * Get all rules for an agent
718
+ */
719
+ getAgentRules(agentId) {
720
+ return Array.from(this.rules.values()).filter(
721
+ (r) => r.agentId === agentId || r.agentId === "*"
722
+ );
723
+ }
724
+ /**
725
+ * Check if access is allowed
726
+ */
727
+ checkAccess(request) {
728
+ const applicableRules = this.findApplicableRules(request);
729
+ if (applicableRules.length === 0) {
730
+ const result2 = {
731
+ allowed: !this.config.strictMode,
732
+ reason: this.config.strictMode ? "No applicable rules found" : "Default permission applied"
733
+ };
734
+ this.logAccess(request, result2);
735
+ return result2;
736
+ }
737
+ const sortedRules = this.sortRulesBySpecificity(applicableRules);
738
+ const bestRule = sortedRules[0];
739
+ if (bestRule.conditions && !this.checkConditions(request, bestRule.conditions)) {
740
+ const result2 = {
741
+ allowed: false,
742
+ reason: "Conditions not met",
743
+ matchedRule: bestRule
744
+ };
745
+ this.logAccess(request, result2);
746
+ return result2;
747
+ }
748
+ const requiredLevel = this.actionToPermissionLevel(request.action);
749
+ const hasPermission = this.hasPermissionLevel(
750
+ bestRule.permission,
751
+ requiredLevel
752
+ );
753
+ const result = {
754
+ allowed: hasPermission,
755
+ reason: hasPermission ? "Permission granted" : "Insufficient permission level",
756
+ matchedRule: bestRule
757
+ };
758
+ this.logAccess(request, result);
759
+ if (hasPermission) {
760
+ this.emit("accessGranted", request);
761
+ } else {
762
+ this.emit("accessDenied", request, result.reason);
763
+ }
764
+ return result;
765
+ }
766
+ /**
767
+ * Grant permission to agent
768
+ */
769
+ grantPermission(granterId, agentId, resource, permission, options) {
770
+ const rule = {
771
+ id: `rule-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`,
772
+ agentId,
773
+ resource,
774
+ permission,
775
+ conditions: options?.conditions,
776
+ expiresAt: options?.expiresAt,
777
+ createdBy: granterId,
778
+ createdAt: Date.now()
779
+ };
780
+ this.addRule(rule);
781
+ return rule;
782
+ }
783
+ /**
784
+ * Revoke all permissions for agent on resource
785
+ */
786
+ revokePermission(agentId, resource) {
787
+ const toRemove = [];
788
+ for (const [id, rule] of this.rules) {
789
+ if (rule.agentId === agentId && rule.resource === resource) {
790
+ toRemove.push(id);
791
+ }
792
+ }
793
+ for (const id of toRemove) {
794
+ this.removeRule(id);
795
+ }
796
+ return toRemove.length;
797
+ }
798
+ /**
799
+ * Check if agent has specific permission
800
+ */
801
+ hasPermission(agentId, resource, action) {
802
+ return this.checkAccess({ agentId, resource, action }).allowed;
803
+ }
804
+ /**
805
+ * Get access log
806
+ */
807
+ getAccessLog(options) {
808
+ let log = [...this.accessLog];
809
+ if (options?.agentId) {
810
+ log = log.filter((e) => e.agentId === options.agentId);
811
+ }
812
+ if (options?.resource) {
813
+ log = log.filter((e) => e.resource === options.resource);
814
+ }
815
+ if (options?.startTime) {
816
+ log = log.filter((e) => e.timestamp >= options.startTime);
817
+ }
818
+ if (options?.endTime) {
819
+ log = log.filter((e) => e.timestamp <= options.endTime);
820
+ }
821
+ log.sort((a, b) => b.timestamp - a.timestamp);
822
+ return options?.limit ? log.slice(0, options.limit) : log;
823
+ }
824
+ /**
825
+ * Clear access log
826
+ */
827
+ clearAccessLog() {
828
+ this.accessLog = [];
829
+ }
830
+ /**
831
+ * Find applicable rules for request
832
+ */
833
+ findApplicableRules(request) {
834
+ const now = Date.now();
835
+ return Array.from(this.rules.values()).filter((rule) => {
836
+ if (rule.expiresAt && rule.expiresAt < now) {
837
+ return false;
838
+ }
839
+ if (rule.agentId !== "*" && rule.agentId !== request.agentId) {
840
+ return false;
841
+ }
842
+ if (rule.resource !== "*" && rule.resource !== request.resource) {
843
+ if (!request.resource.startsWith(rule.resource + ":")) {
844
+ return false;
845
+ }
846
+ }
847
+ return true;
848
+ });
849
+ }
850
+ /**
851
+ * Sort rules by specificity (most specific first)
852
+ */
853
+ sortRulesBySpecificity(rules) {
854
+ return rules.sort((a, b) => {
855
+ const agentSpecA = a.agentId !== "*" ? 1 : 0;
856
+ const agentSpecB = b.agentId !== "*" ? 1 : 0;
857
+ if (agentSpecA !== agentSpecB) return agentSpecB - agentSpecA;
858
+ const resourceSpecA = a.resource !== "*" ? 1 : 0;
859
+ const resourceSpecB = b.resource !== "*" ? 1 : 0;
860
+ if (resourceSpecA !== resourceSpecB) return resourceSpecB - resourceSpecA;
861
+ const levelA = this.permissionToLevel(a.permission);
862
+ const levelB = this.permissionToLevel(b.permission);
863
+ return levelB - levelA;
864
+ });
865
+ }
866
+ /**
867
+ * Check conditions
868
+ */
869
+ checkConditions(request, conditions) {
870
+ const now = Date.now();
871
+ for (const condition of conditions) {
872
+ switch (condition.type) {
873
+ case "time-range": {
874
+ const { start, end } = condition.value;
875
+ if (now < start || now > end) return false;
876
+ break;
877
+ }
878
+ case "entry-type": {
879
+ if (!request.entry) break;
880
+ const allowedTypes = condition.value;
881
+ if (!allowedTypes.includes(request.entry.type)) return false;
882
+ break;
883
+ }
884
+ case "importance": {
885
+ if (!request.entry) break;
886
+ const { min, max } = condition.value;
887
+ if (min !== void 0 && request.entry.importance < min) return false;
888
+ if (max !== void 0 && request.entry.importance > max) return false;
889
+ break;
890
+ }
891
+ case "custom": {
892
+ const fn = condition.value;
893
+ if (!fn(request)) return false;
894
+ break;
895
+ }
896
+ }
897
+ }
898
+ return true;
899
+ }
900
+ /**
901
+ * Convert action to required permission level
902
+ */
903
+ actionToPermissionLevel(action) {
904
+ switch (action) {
905
+ case "read":
906
+ return 1;
907
+ case "write":
908
+ return 2;
909
+ case "delete":
910
+ return 2;
911
+ case "admin":
912
+ return 3;
913
+ default:
914
+ return 1;
915
+ }
916
+ }
917
+ /**
918
+ * Convert permission to level number
919
+ */
920
+ permissionToLevel(permission) {
921
+ switch (permission) {
922
+ case "none":
923
+ return 0;
924
+ case "read":
925
+ return 1;
926
+ case "write":
927
+ return 2;
928
+ case "admin":
929
+ return 3;
930
+ default:
931
+ return 0;
932
+ }
933
+ }
934
+ /**
935
+ * Check if permission level is sufficient
936
+ */
937
+ hasPermissionLevel(permission, required) {
938
+ return this.permissionToLevel(permission) >= required;
939
+ }
940
+ /**
941
+ * Log access attempt
942
+ */
943
+ logAccess(request, result) {
944
+ if (!this.config.enableAuditLog) return;
945
+ this.accessLog.push({
946
+ timestamp: Date.now(),
947
+ agentId: request.agentId,
948
+ resource: request.resource,
949
+ action: request.action,
950
+ allowed: result.allowed,
951
+ reason: result.reason
952
+ });
953
+ if (this.accessLog.length > this.maxLogSize) {
954
+ this.accessLog = this.accessLog.slice(-this.maxLogSize);
955
+ }
956
+ }
957
+ /**
958
+ * Get statistics
959
+ */
960
+ getStats() {
961
+ const agents = new Set(
962
+ Array.from(this.rules.values()).filter((r) => r.agentId !== "*").map((r) => r.agentId)
963
+ );
964
+ const granted = this.accessLog.filter((e) => e.allowed).length;
965
+ const denied = this.accessLog.filter((e) => !e.allowed).length;
966
+ return {
967
+ totalRules: this.rules.size,
968
+ agentCount: agents.size,
969
+ accessGranted: granted,
970
+ accessDenied: denied
971
+ };
972
+ }
973
+ /**
974
+ * Export rules
975
+ */
976
+ exportRules() {
977
+ return Array.from(this.rules.values());
978
+ }
979
+ /**
980
+ * Import rules
981
+ */
982
+ importRules(rules) {
983
+ let imported = 0;
984
+ for (const rule of rules) {
985
+ if (this.addRule(rule)) {
986
+ imported++;
987
+ }
988
+ }
989
+ return imported;
990
+ }
991
+ };
992
+ function createAccessControl(config) {
993
+ return new AccessControl(config);
994
+ }
995
+ // Annotate the CommonJS export names for ESM import in node:
996
+ 0 && (module.exports = {
997
+ AccessControl,
998
+ NamespaceManager,
999
+ SharedMemory,
1000
+ createAccessControl,
1001
+ createNamespaceManager,
1002
+ createSharedMemory
1003
+ });