server-memory-enhanced 2.3.0 → 2.3.2

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 (32) hide show
  1. package/README.md +245 -44
  2. package/dist/index.js +27 -1
  3. package/dist/lib/analysis/analytics-service.js +111 -0
  4. package/dist/lib/analysis/conflict-detector.js +48 -0
  5. package/dist/lib/analysis/context-builder.js +31 -0
  6. package/dist/lib/analysis/memory-stats.js +63 -0
  7. package/dist/lib/analysis/path-finder.js +77 -0
  8. package/dist/lib/collaboration/conversation-service.js +43 -0
  9. package/dist/lib/collaboration/flag-manager.js +38 -0
  10. package/dist/lib/jsonl-storage-adapter.js +8 -4
  11. package/dist/lib/knowledge-graph-manager.js +94 -663
  12. package/dist/lib/maintenance/bulk-updater.js +44 -0
  13. package/dist/lib/maintenance/memory-pruner.js +48 -0
  14. package/dist/lib/operations/entity-operations.js +27 -0
  15. package/dist/lib/operations/observation-operations.js +105 -0
  16. package/dist/lib/operations/relation-operations.js +45 -0
  17. package/dist/lib/queries/entity-queries.js +68 -0
  18. package/dist/lib/queries/graph-reader.js +9 -0
  19. package/dist/lib/queries/search-service.js +99 -0
  20. package/dist/lib/schemas.js +15 -0
  21. package/dist/lib/utils/entity-finder.js +31 -0
  22. package/dist/lib/utils/negation-detector.js +23 -0
  23. package/dist/lib/utils/observation-validator.js +43 -0
  24. package/dist/lib/utils/relation-key.js +16 -0
  25. package/dist/lib/validation/entity-type-validator.js +32 -0
  26. package/dist/lib/validation/observation-validator.js +61 -0
  27. package/dist/lib/validation/quality-scorer.js +27 -0
  28. package/dist/lib/validation/relation-validator.js +36 -0
  29. package/dist/lib/validation/request-validator.js +91 -0
  30. package/dist/lib/validation.js +8 -200
  31. package/dist/lib/versioning/observation-history.js +54 -0
  32. package/package.json +1 -1
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Path finding service for the knowledge graph
3
+ */
4
+ /**
5
+ * Find the shortest path between two entities in the knowledge graph
6
+ * Uses BFS algorithm with bidirectional search
7
+ */
8
+ export async function findRelationPath(storage, from, to, maxDepth = 5) {
9
+ const graph = await storage.loadGraph();
10
+ if (from === to) {
11
+ return { found: true, path: [from], relations: [] };
12
+ }
13
+ // Build indexes for efficient relation lookup
14
+ const relationsFrom = new Map();
15
+ const relationsTo = new Map();
16
+ for (const rel of graph.relations) {
17
+ if (!relationsFrom.has(rel.from)) {
18
+ relationsFrom.set(rel.from, []);
19
+ }
20
+ relationsFrom.get(rel.from).push(rel);
21
+ if (!relationsTo.has(rel.to)) {
22
+ relationsTo.set(rel.to, []);
23
+ }
24
+ relationsTo.get(rel.to).push(rel);
25
+ }
26
+ // BFS to find shortest path
27
+ const queue = [
28
+ { entity: from, path: [from], relations: [] }
29
+ ];
30
+ const visited = new Set([from]);
31
+ while (queue.length > 0) {
32
+ const current = queue.shift();
33
+ if (current.path.length > maxDepth) {
34
+ continue;
35
+ }
36
+ // Find all relations connected to current entity (both outgoing and incoming for bidirectional search)
37
+ const outgoing = relationsFrom.get(current.entity) || [];
38
+ const incoming = relationsTo.get(current.entity) || [];
39
+ // Check outgoing relations
40
+ for (const rel of outgoing) {
41
+ if (rel.to === to) {
42
+ return {
43
+ found: true,
44
+ path: [...current.path, rel.to],
45
+ relations: [...current.relations, rel]
46
+ };
47
+ }
48
+ if (!visited.has(rel.to)) {
49
+ visited.add(rel.to);
50
+ queue.push({
51
+ entity: rel.to,
52
+ path: [...current.path, rel.to],
53
+ relations: [...current.relations, rel]
54
+ });
55
+ }
56
+ }
57
+ // Check incoming relations (traverse backwards)
58
+ for (const rel of incoming) {
59
+ if (rel.from === to) {
60
+ return {
61
+ found: true,
62
+ path: [...current.path, rel.from],
63
+ relations: [...current.relations, rel]
64
+ };
65
+ }
66
+ if (!visited.has(rel.from)) {
67
+ visited.add(rel.from);
68
+ queue.push({
69
+ entity: rel.from,
70
+ path: [...current.path, rel.from],
71
+ relations: [...current.relations, rel]
72
+ });
73
+ }
74
+ }
75
+ }
76
+ return { found: false, path: [], relations: [] };
77
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Conversation service (agent threads)
3
+ */
4
+ /**
5
+ * List all conversations (agent threads) with summary information
6
+ */
7
+ export async function listConversations(storage) {
8
+ const graph = await storage.loadGraph();
9
+ // Group data by agent thread
10
+ const threadMap = new Map();
11
+ // Collect entities by thread
12
+ for (const entity of graph.entities) {
13
+ if (!threadMap.has(entity.agentThreadId)) {
14
+ threadMap.set(entity.agentThreadId, { entities: [], relations: [], timestamps: [] });
15
+ }
16
+ const threadData = threadMap.get(entity.agentThreadId);
17
+ threadData.entities.push(entity);
18
+ threadData.timestamps.push(entity.timestamp);
19
+ }
20
+ // Collect relations by thread
21
+ for (const relation of graph.relations) {
22
+ if (!threadMap.has(relation.agentThreadId)) {
23
+ threadMap.set(relation.agentThreadId, { entities: [], relations: [], timestamps: [] });
24
+ }
25
+ const threadData = threadMap.get(relation.agentThreadId);
26
+ threadData.relations.push(relation);
27
+ threadData.timestamps.push(relation.timestamp);
28
+ }
29
+ // Build conversation summaries
30
+ const conversations = Array.from(threadMap.entries()).map(([agentThreadId, data]) => {
31
+ const timestamps = data.timestamps.sort((a, b) => a.localeCompare(b));
32
+ return {
33
+ agentThreadId,
34
+ entityCount: data.entities.length,
35
+ relationCount: data.relations.length,
36
+ firstCreated: timestamps[0] || '',
37
+ lastUpdated: timestamps[timestamps.length - 1] || ''
38
+ };
39
+ });
40
+ // Sort by last updated (most recent first)
41
+ conversations.sort((a, b) => b.lastUpdated.localeCompare(a.lastUpdated));
42
+ return { conversations };
43
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Collaboration features (flagging, review)
3
+ */
4
+ import { randomUUID } from 'crypto';
5
+ /**
6
+ * Flag an entity for review
7
+ */
8
+ export async function flagForReview(storage, entityName, reason, reviewer) {
9
+ const graph = await storage.loadGraph();
10
+ const entity = graph.entities.find(e => e.name === entityName);
11
+ if (!entity) {
12
+ throw new Error(`Entity with name ${entityName} not found`);
13
+ }
14
+ // Add a special observation to mark for review
15
+ const flagContent = `[FLAGGED FOR REVIEW: ${reason}${reviewer ? ` - Reviewer: ${reviewer}` : ''}]`;
16
+ // Check if this flag already exists (by content)
17
+ if (!entity.observations.some(o => o.content === flagContent)) {
18
+ const flagObservation = {
19
+ id: `obs_${randomUUID()}`,
20
+ content: flagContent,
21
+ timestamp: new Date().toISOString(),
22
+ version: 1,
23
+ agentThreadId: entity.agentThreadId,
24
+ confidence: 1.0, // Flag observations have full confidence
25
+ importance: 1.0 // Flag observations are highly important
26
+ };
27
+ entity.observations.push(flagObservation);
28
+ entity.timestamp = new Date().toISOString();
29
+ await storage.saveGraph(graph);
30
+ }
31
+ }
32
+ /**
33
+ * Get all entities flagged for review
34
+ */
35
+ export async function getFlaggedEntities(storage) {
36
+ const graph = await storage.loadGraph();
37
+ return graph.entities.filter(e => e.observations.some(obs => obs.content.includes('[FLAGGED FOR REVIEW:')));
38
+ }
@@ -240,10 +240,14 @@ export class JsonlStorageAdapter {
240
240
  * Serialize thread data to JSONL lines
241
241
  */
242
242
  serializeThreadData(threadData) {
243
- return [
244
- ...threadData.entities.map(e => this.serializeEntity(e)),
245
- ...threadData.relations.map(r => this.serializeRelation(r))
246
- ];
243
+ const lines = [];
244
+ for (const e of threadData.entities) {
245
+ lines.push(this.serializeEntity(e));
246
+ }
247
+ for (const r of threadData.relations) {
248
+ lines.push(this.serializeRelation(r));
249
+ }
250
+ return lines;
247
251
  }
248
252
  /**
249
253
  * Save data for a specific thread