agentdb 3.0.0-alpha.11 → 3.0.0-alpha.13

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 (107) hide show
  1. package/dist/src/backends/graph/GraphDatabaseAdapter.d.ts +54 -0
  2. package/dist/src/backends/graph/GraphDatabaseAdapter.d.ts.map +1 -1
  3. package/dist/src/backends/graph/GraphDatabaseAdapter.js +125 -0
  4. package/dist/src/backends/graph/GraphDatabaseAdapter.js.map +1 -1
  5. package/dist/src/cli/agentdb-cli.js +0 -0
  6. package/dist/src/controllers/ReflexionMemory.d.ts +50 -0
  7. package/dist/src/controllers/ReflexionMemory.d.ts.map +1 -1
  8. package/dist/src/controllers/ReflexionMemory.js +258 -0
  9. package/dist/src/controllers/ReflexionMemory.js.map +1 -1
  10. package/dist/src/controllers/index.d.ts +2 -0
  11. package/dist/src/controllers/index.d.ts.map +1 -1
  12. package/dist/src/controllers/index.js +2 -0
  13. package/dist/src/controllers/index.js.map +1 -1
  14. package/dist/src/controllers/prerequisites.d.ts +76 -0
  15. package/dist/src/controllers/prerequisites.d.ts.map +1 -0
  16. package/dist/src/controllers/prerequisites.js +235 -0
  17. package/dist/src/controllers/prerequisites.js.map +1 -0
  18. package/dist/src/db-fallback.d.ts.map +1 -1
  19. package/dist/src/db-fallback.js +55 -45
  20. package/dist/src/db-fallback.js.map +1 -1
  21. package/package.json +1 -1
  22. package/dist/schemas/frontier-schema.sql +0 -378
  23. package/dist/schemas/schema.sql +0 -382
  24. package/dist/src/backends/index.cjs +0 -6
  25. package/dist/src/backends/ruvector/GuardedVectorBackend.d.ts +0 -93
  26. package/dist/src/backends/ruvector/GuardedVectorBackend.d.ts.map +0 -1
  27. package/dist/src/backends/ruvector/GuardedVectorBackend.js +0 -182
  28. package/dist/src/backends/ruvector/GuardedVectorBackend.js.map +0 -1
  29. package/dist/src/consensus/RaftConsensus.d.ts +0 -220
  30. package/dist/src/consensus/RaftConsensus.d.ts.map +0 -1
  31. package/dist/src/consensus/RaftConsensus.js +0 -762
  32. package/dist/src/consensus/RaftConsensus.js.map +0 -1
  33. package/dist/src/controllers/HierarchicalMemory.d.ts +0 -197
  34. package/dist/src/controllers/HierarchicalMemory.d.ts.map +0 -1
  35. package/dist/src/controllers/HierarchicalMemory.js +0 -519
  36. package/dist/src/controllers/HierarchicalMemory.js.map +0 -1
  37. package/dist/src/controllers/MemoryConsolidation.d.ts +0 -142
  38. package/dist/src/controllers/MemoryConsolidation.d.ts.map +0 -1
  39. package/dist/src/controllers/MemoryConsolidation.js +0 -479
  40. package/dist/src/controllers/MemoryConsolidation.js.map +0 -1
  41. package/dist/src/controllers/QUICConnection.d.ts +0 -122
  42. package/dist/src/controllers/QUICConnection.d.ts.map +0 -1
  43. package/dist/src/controllers/QUICConnection.js +0 -329
  44. package/dist/src/controllers/QUICConnection.js.map +0 -1
  45. package/dist/src/controllers/QUICConnectionPool.d.ts +0 -83
  46. package/dist/src/controllers/QUICConnectionPool.d.ts.map +0 -1
  47. package/dist/src/controllers/QUICConnectionPool.js +0 -256
  48. package/dist/src/controllers/QUICConnectionPool.js.map +0 -1
  49. package/dist/src/controllers/QUICStreamManager.d.ts +0 -114
  50. package/dist/src/controllers/QUICStreamManager.d.ts.map +0 -1
  51. package/dist/src/controllers/QUICStreamManager.js +0 -267
  52. package/dist/src/controllers/QUICStreamManager.js.map +0 -1
  53. package/dist/src/controllers/StreamingEmbeddingService.d.ts +0 -82
  54. package/dist/src/controllers/StreamingEmbeddingService.d.ts.map +0 -1
  55. package/dist/src/controllers/StreamingEmbeddingService.js +0 -243
  56. package/dist/src/controllers/StreamingEmbeddingService.js.map +0 -1
  57. package/dist/src/controllers/index.cjs +0 -6
  58. package/dist/src/coordination/MultiDatabaseCoordinator.d.ts +0 -348
  59. package/dist/src/coordination/MultiDatabaseCoordinator.d.ts.map +0 -1
  60. package/dist/src/coordination/MultiDatabaseCoordinator.js +0 -803
  61. package/dist/src/coordination/MultiDatabaseCoordinator.js.map +0 -1
  62. package/dist/src/coordination/index.d.ts +0 -10
  63. package/dist/src/coordination/index.d.ts.map +0 -1
  64. package/dist/src/coordination/index.js +0 -10
  65. package/dist/src/coordination/index.js.map +0 -1
  66. package/dist/src/index.cjs +0 -6
  67. package/dist/src/optimizations/RVFOptimizer.d.ts +0 -226
  68. package/dist/src/optimizations/RVFOptimizer.d.ts.map +0 -1
  69. package/dist/src/optimizations/RVFOptimizer.js +0 -541
  70. package/dist/src/optimizations/RVFOptimizer.js.map +0 -1
  71. package/dist/src/security/AttestationLog.d.ts +0 -70
  72. package/dist/src/security/AttestationLog.d.ts.map +0 -1
  73. package/dist/src/security/AttestationLog.js +0 -174
  74. package/dist/src/security/AttestationLog.js.map +0 -1
  75. package/dist/src/security/MutationGuard.d.ts +0 -83
  76. package/dist/src/security/MutationGuard.d.ts.map +0 -1
  77. package/dist/src/security/MutationGuard.js +0 -364
  78. package/dist/src/security/MutationGuard.js.map +0 -1
  79. package/dist/src/security/index.cjs +0 -6
  80. package/dist/src/security/index.d.ts +0 -15
  81. package/dist/src/security/index.d.ts.map +0 -1
  82. package/dist/src/security/index.js +0 -18
  83. package/dist/src/security/index.js.map +0 -1
  84. package/dist/src/services/GNNService.d.ts +0 -173
  85. package/dist/src/services/GNNService.d.ts.map +0 -1
  86. package/dist/src/services/GNNService.js +0 -639
  87. package/dist/src/services/GNNService.js.map +0 -1
  88. package/dist/src/services/GraphTransformerService.d.ts +0 -80
  89. package/dist/src/services/GraphTransformerService.d.ts.map +0 -1
  90. package/dist/src/services/GraphTransformerService.js +0 -369
  91. package/dist/src/services/GraphTransformerService.js.map +0 -1
  92. package/dist/src/services/SemanticRouter.d.ts +0 -83
  93. package/dist/src/services/SemanticRouter.d.ts.map +0 -1
  94. package/dist/src/services/SemanticRouter.js +0 -160
  95. package/dist/src/services/SemanticRouter.js.map +0 -1
  96. package/dist/src/services/SonaTrajectoryService.d.ts +0 -224
  97. package/dist/src/services/SonaTrajectoryService.d.ts.map +0 -1
  98. package/dist/src/services/SonaTrajectoryService.js +0 -539
  99. package/dist/src/services/SonaTrajectoryService.js.map +0 -1
  100. package/dist/src/utils/LegacyAttentionAdapter.d.ts +0 -93
  101. package/dist/src/utils/LegacyAttentionAdapter.d.ts.map +0 -1
  102. package/dist/src/utils/LegacyAttentionAdapter.js +0 -241
  103. package/dist/src/utils/LegacyAttentionAdapter.js.map +0 -1
  104. package/dist/src/utils/vector-math.d.ts +0 -29
  105. package/dist/src/utils/vector-math.d.ts.map +0 -1
  106. package/dist/src/utils/vector-math.js +0 -66
  107. package/dist/src/utils/vector-math.js.map +0 -1
@@ -1,639 +0,0 @@
1
- /**
2
- * GNNService - Graph Neural Network Integration
3
- *
4
- * Provides high-level GNN capabilities on top of @ruvector/gnn:
5
- * - Semantic intent classification
6
- * - Graph-based skill recommendations
7
- * - Code pattern similarity via graph embeddings
8
- *
9
- * Tries native @ruvector/gnn first (NAPI-RS), falls back to JS.
10
- * All public methods are safe to call regardless of engine availability.
11
- *
12
- * Performance targets (ADR-062):
13
- * - 100x-50000x speedup when native @ruvector/gnn is available
14
- * - Zero-overhead JS fallback when native is not present
15
- */
16
- export class GNNService {
17
- gnn = null;
18
- engineType = 'js';
19
- initialized = false;
20
- config;
21
- constructor(config) {
22
- // Default to 8 heads (128 % 8 = 0, valid for MultiHeadAttention)
23
- const heads = config?.heads ?? config?.layers ?? 8;
24
- this.config = {
25
- inputDim: config?.inputDim ?? 384,
26
- hiddenDim: config?.hiddenDim ?? 128,
27
- outputDim: config?.outputDim ?? 64,
28
- heads,
29
- };
30
- }
31
- /**
32
- * Initialize the GNN engine.
33
- *
34
- * Attempts to load @ruvector/gnn and create a GNN layer.
35
- * Falls back to JS-based heuristics if unavailable.
36
- */
37
- async initialize() {
38
- if (this.initialized)
39
- return;
40
- try {
41
- const mod = await import('@ruvector/gnn');
42
- const RuvectorLayer = mod.RuvectorLayer ||
43
- mod.default?.RuvectorLayer ||
44
- mod.GNN ||
45
- mod.default?.GNN;
46
- if (RuvectorLayer) {
47
- // @ruvector/gnn@0.1.25+ uses Result-based constructors
48
- // RuvectorLayer(inputDim, hiddenDim, numHeads, dropout)
49
- // numHeads must divide hiddenDim evenly (e.g., 128 % 8 = 0)
50
- // Validate head count before calling native constructor
51
- if (this.config.hiddenDim % this.config.heads !== 0) {
52
- const validHeads = [];
53
- for (let h = 1; h <= this.config.hiddenDim; h *= 2) {
54
- if (this.config.hiddenDim % h === 0)
55
- validHeads.push(h);
56
- }
57
- throw new Error(`Invalid head count: ${this.config.heads}. ` +
58
- `hiddenDim (${this.config.hiddenDim}) must be divisible by heads. ` +
59
- `Valid options: [${validHeads.join(', ')}]`);
60
- }
61
- try {
62
- this.gnn = new RuvectorLayer(this.config.inputDim, this.config.hiddenDim, this.config.heads, // FIXED: Use heads parameter (not layers)
63
- 0.1 // dropout
64
- );
65
- this.engineType = 'native';
66
- this.initialized = true;
67
- console.log(`[GNNService] Using native @ruvector/gnn (v0.1.25+) with ${this.config.heads} heads`);
68
- return;
69
- }
70
- catch (constructorError) {
71
- // @ruvector/gnn@0.1.25+ throws errors instead of panicking
72
- const errMsg = constructorError instanceof Error
73
- ? constructorError.message
74
- : String(constructorError);
75
- console.warn(`[GNNService] Native GNN constructor failed: ${errMsg}`);
76
- console.warn('[GNNService] Falling back to JS implementation');
77
- }
78
- }
79
- }
80
- catch (e) {
81
- const msg = e instanceof Error ? e.message : String(e);
82
- console.warn(`[GNNService] Native GNN not available: ${msg}`);
83
- }
84
- this.engineType = 'js';
85
- this.initialized = true;
86
- console.log('[GNNService] Using JS fallback');
87
- }
88
- /**
89
- * Semantic intent classification.
90
- *
91
- * When native GNN is available, runs a forward pass on the embedding
92
- * and maps logits to intent categories. Otherwise uses keyword matching.
93
- */
94
- async classifyIntent(query, embedding) {
95
- if (!this.initialized)
96
- await this.initialize();
97
- const intents = ['search', 'create', 'update', 'delete', 'analyze'];
98
- if (this.engineType === 'native' && this.gnn) {
99
- try {
100
- const logits = typeof this.gnn.forward === 'function'
101
- ? this.gnn.forward(embedding, [], [])
102
- : null;
103
- if (logits && logits.length >= intents.length) {
104
- const logitArray = logits instanceof Float32Array
105
- ? Array.from(logits)
106
- : logits;
107
- // Softmax over intent logits
108
- const expLogits = logitArray.slice(0, intents.length).map((l) => Math.exp(l));
109
- const expSum = expLogits.reduce((s, v) => s + v, 1e-10);
110
- const probs = expLogits.map((e) => e / expSum);
111
- let maxIdx = 0;
112
- for (let i = 1; i < probs.length; i++) {
113
- if (probs[i] > probs[maxIdx])
114
- maxIdx = i;
115
- }
116
- return {
117
- intent: intents[maxIdx],
118
- confidence: probs[maxIdx],
119
- logits: logitArray,
120
- };
121
- }
122
- }
123
- catch {
124
- // Fall through to JS
125
- }
126
- }
127
- // JS fallback: keyword matching
128
- const queryLower = query.toLowerCase();
129
- if (queryLower.includes('search') || queryLower.includes('find') || queryLower.includes('lookup')) {
130
- return { intent: 'search', confidence: 0.8 };
131
- }
132
- if (queryLower.includes('create') || queryLower.includes('add') || queryLower.includes('new')) {
133
- return { intent: 'create', confidence: 0.8 };
134
- }
135
- if (queryLower.includes('update') || queryLower.includes('edit') || queryLower.includes('modify')) {
136
- return { intent: 'update', confidence: 0.8 };
137
- }
138
- if (queryLower.includes('delete') || queryLower.includes('remove') || queryLower.includes('drop')) {
139
- return { intent: 'delete', confidence: 0.8 };
140
- }
141
- if (queryLower.includes('analyze') || queryLower.includes('report') || queryLower.includes('summary')) {
142
- return { intent: 'analyze', confidence: 0.8 };
143
- }
144
- return { intent: 'search', confidence: 0.5 };
145
- }
146
- /**
147
- * Graph-based skill recommendations.
148
- *
149
- * Uses GNN node classification when available, otherwise
150
- * returns adjacent skills from the skill graph map.
151
- */
152
- async recommendSkills(currentSkill, skillGraph) {
153
- if (!this.initialized)
154
- await this.initialize();
155
- if (this.engineType === 'native' && this.gnn) {
156
- try {
157
- // Build adjacency from skill graph for GNN
158
- const skills = Object.keys(skillGraph);
159
- const idx = skills.indexOf(currentSkill);
160
- if (idx >= 0 && typeof this.gnn.forward === 'function') {
161
- // Create a simple embedding from the skill index
162
- const skillEmbed = new Float32Array(this.config.inputDim);
163
- skillEmbed[idx % this.config.inputDim] = 1.0;
164
- const neighborEmbeds = [];
165
- const weights = [];
166
- const neighbors = skillGraph[currentSkill] || [];
167
- for (const neighbor of neighbors) {
168
- const nIdx = skills.indexOf(neighbor);
169
- if (nIdx >= 0) {
170
- const nEmbed = new Float32Array(this.config.inputDim);
171
- nEmbed[nIdx % this.config.inputDim] = 1.0;
172
- neighborEmbeds.push(nEmbed);
173
- weights.push(1.0);
174
- }
175
- }
176
- if (neighborEmbeds.length > 0) {
177
- const enhanced = this.gnn.forward(skillEmbed, neighborEmbeds, weights);
178
- if (enhanced) {
179
- // Use enhanced embedding to rank skills by similarity
180
- const ranked = skills
181
- .filter(s => s !== currentSkill)
182
- .map(s => {
183
- const sIdx = skills.indexOf(s);
184
- return { skill: s, score: enhanced[sIdx % enhanced.length] || 0 };
185
- })
186
- .sort((a, b) => b.score - a.score);
187
- return ranked.slice(0, 5).map(r => r.skill);
188
- }
189
- }
190
- }
191
- }
192
- catch {
193
- // Fall through to JS
194
- }
195
- }
196
- // JS fallback: return direct neighbors from graph
197
- const neighbors = skillGraph[currentSkill] || [];
198
- if (neighbors.length > 0) {
199
- return neighbors.slice(0, 5);
200
- }
201
- return Object.keys(skillGraph).filter(s => s !== currentSkill).slice(0, 5);
202
- }
203
- /**
204
- * Find similar code patterns using graph embedding similarity.
205
- *
206
- * When native GNN is available, uses graph-level similarity.
207
- * Otherwise falls back to cosine similarity.
208
- */
209
- async findSimilarPatterns(pattern, patterns) {
210
- if (!this.initialized)
211
- await this.initialize();
212
- if (this.engineType === 'native' && this.gnn) {
213
- try {
214
- const query = pattern instanceof Float32Array
215
- ? pattern
216
- : new Float32Array(pattern);
217
- const candidates = patterns.map(p => p instanceof Float32Array ? p : new Float32Array(p));
218
- // Use differentiable search if available
219
- if (typeof this.gnn.forward === 'function') {
220
- const enhanced = this.gnn.forward(query, candidates, candidates.map(() => 1.0));
221
- if (enhanced) {
222
- return patterns.map((_, i) => ({
223
- index: i,
224
- similarity: this.cosineSim(Array.from(enhanced), patterns[i]),
225
- })).sort((a, b) => b.similarity - a.similarity);
226
- }
227
- }
228
- }
229
- catch {
230
- // Fall through to JS
231
- }
232
- }
233
- // JS fallback: cosine similarity
234
- return patterns.map((p, i) => ({
235
- index: i,
236
- similarity: this.cosineSim(pattern, p),
237
- })).sort((a, b) => b.similarity - a.similarity);
238
- }
239
- /**
240
- * Get the current engine type.
241
- */
242
- getEngineType() {
243
- return this.engineType;
244
- }
245
- /**
246
- * Check if the service is initialized.
247
- */
248
- isInitialized() {
249
- return this.initialized;
250
- }
251
- /**
252
- * Get service statistics.
253
- */
254
- getStats() {
255
- return {
256
- engineType: this.engineType,
257
- initialized: this.initialized,
258
- config: this.config,
259
- };
260
- }
261
- /**
262
- * Graph Convolutional Network (GCN) for skill matching.
263
- *
264
- * Uses GCN layers to learn representations of skills based on their
265
- * relationships in the skill graph. Achieves >90% accuracy when native.
266
- */
267
- async matchSkillsGCN(taskEmbedding, skillGraph, topK = 5) {
268
- if (!this.initialized)
269
- await this.initialize();
270
- if (this.engineType === 'native' && this.gnn) {
271
- try {
272
- const skills = Object.keys(skillGraph);
273
- const results = [];
274
- for (const skill of skills) {
275
- const skillData = skillGraph[skill];
276
- const neighborEmbeddings = [];
277
- const weights = [];
278
- // Collect neighbor embeddings for GCN aggregation
279
- for (const neighbor of skillData.neighbors) {
280
- if (skillGraph[neighbor]) {
281
- neighborEmbeddings.push(skillGraph[neighbor].embedding);
282
- weights.push(1.0 / skillData.neighbors.length); // Normalized weights
283
- }
284
- }
285
- // Forward pass through GCN
286
- if (typeof this.gnn.forward === 'function') {
287
- const enhanced = this.gnn.forward(skillData.embedding, neighborEmbeddings, weights);
288
- if (enhanced) {
289
- const similarity = this.cosineSim(taskEmbedding, enhanced);
290
- results.push({
291
- skill,
292
- score: similarity,
293
- confidence: similarity > 0.8 ? 0.95 : similarity > 0.6 ? 0.85 : 0.75,
294
- });
295
- }
296
- }
297
- }
298
- return results
299
- .sort((a, b) => b.score - a.score)
300
- .slice(0, topK);
301
- }
302
- catch (e) {
303
- console.warn('[GNNService] GCN skill matching failed, falling back:', e);
304
- }
305
- }
306
- // JS fallback: simple cosine similarity without graph convolution
307
- const skills = Object.keys(skillGraph);
308
- return skills
309
- .map(skill => ({
310
- skill,
311
- score: this.cosineSim(taskEmbedding, skillGraph[skill].embedding),
312
- confidence: 0.6,
313
- }))
314
- .sort((a, b) => b.score - a.score)
315
- .slice(0, topK);
316
- }
317
- /**
318
- * Graph Attention Network (GAT) for context understanding.
319
- *
320
- * Applies attention mechanisms to weight the importance of different
321
- * context nodes when making predictions.
322
- */
323
- async understandContextGAT(queryEmbedding, contextNodes, attentionHeads = 4) {
324
- if (!this.initialized)
325
- await this.initialize();
326
- if (this.engineType === 'native' && this.gnn) {
327
- try {
328
- const embeddings = contextNodes.map(n => n.embedding);
329
- const weights = new Array(contextNodes.length).fill(1.0);
330
- // Multi-head attention via forward pass
331
- if (typeof this.gnn.forward === 'function') {
332
- const attended = this.gnn.forward(queryEmbedding, embeddings, weights);
333
- if (attended) {
334
- // Calculate attention weights based on similarity
335
- const attentionWeights = {};
336
- let maxWeight = 0;
337
- for (let i = 0; i < contextNodes.length; i++) {
338
- const weight = this.cosineSim(attended, contextNodes[i].embedding);
339
- attentionWeights[contextNodes[i].id] = weight;
340
- maxWeight = Math.max(maxWeight, weight);
341
- }
342
- // Normalize weights
343
- for (const key in attentionWeights) {
344
- attentionWeights[key] /= maxWeight || 1.0;
345
- }
346
- // Find dominant types
347
- const typeWeights = {};
348
- for (const node of contextNodes) {
349
- typeWeights[node.type] = (typeWeights[node.type] || 0) + attentionWeights[node.id];
350
- }
351
- const dominantTypes = Object.entries(typeWeights)
352
- .sort(([, a], [, b]) => b - a)
353
- .slice(0, 3)
354
- .map(([type]) => type);
355
- return {
356
- contextVector: attended,
357
- attentionWeights,
358
- dominantTypes,
359
- };
360
- }
361
- }
362
- }
363
- catch (e) {
364
- console.warn('[GNNService] GAT context understanding failed, falling back:', e);
365
- }
366
- }
367
- // JS fallback: uniform attention
368
- const avgEmbedding = new Float32Array(queryEmbedding.length);
369
- for (const node of contextNodes) {
370
- for (let i = 0; i < avgEmbedding.length; i++) {
371
- avgEmbedding[i] += node.embedding[i] / contextNodes.length;
372
- }
373
- }
374
- const attentionWeights = {};
375
- contextNodes.forEach(n => {
376
- attentionWeights[n.id] = 1.0 / contextNodes.length;
377
- });
378
- const typeWeights = {};
379
- for (const node of contextNodes) {
380
- typeWeights[node.type] = (typeWeights[node.type] || 0) + 1;
381
- }
382
- const dominantTypes = Object.entries(typeWeights)
383
- .sort(([, a], [, b]) => b - a)
384
- .map(([type]) => type);
385
- return {
386
- contextVector: avgEmbedding,
387
- attentionWeights,
388
- dominantTypes,
389
- };
390
- }
391
- /**
392
- * Process heterogeneous graphs with multiple node and edge types.
393
- *
394
- * Handles graphs with different types of entities (agents, tasks, skills)
395
- * and relationships (depends_on, requires, similar_to).
396
- */
397
- async processHeterogeneousGraph(graph, queryNodeId) {
398
- if (!this.initialized)
399
- await this.initialize();
400
- const nodeMap = new Map(graph.nodes.map(n => [n.id, n]));
401
- const queryNode = nodeMap.get(queryNodeId);
402
- if (!queryNode) {
403
- throw new Error(`Query node ${queryNodeId} not found in graph`);
404
- }
405
- if (this.engineType === 'native' && this.gnn) {
406
- try {
407
- // Build adjacency for heterogeneous GNN
408
- const neighbors = graph.edges
409
- .filter(e => e.from === queryNodeId)
410
- .map(e => {
411
- const neighbor = nodeMap.get(e.to);
412
- return neighbor ? { ...neighbor, edgeType: e.type, weight: e.weight } : null;
413
- })
414
- .filter(n => n !== null);
415
- if (neighbors.length > 0 && typeof this.gnn.forward === 'function') {
416
- const enhanced = this.gnn.forward(queryNode.embedding, neighbors.map(n => n.embedding), neighbors.map(n => n.weight));
417
- if (enhanced) {
418
- // Calculate relevance for all nodes
419
- const relatedNodes = graph.nodes
420
- .filter(n => n.id !== queryNodeId)
421
- .map(n => ({
422
- id: n.id,
423
- type: n.type,
424
- relevance: this.cosineSim(enhanced, n.embedding),
425
- }))
426
- .sort((a, b) => b.relevance - a.relevance)
427
- .slice(0, 10);
428
- // Find strongest pathways
429
- const pathways = this.findStrongPathways(graph, queryNodeId, relatedNodes.slice(0, 5));
430
- return {
431
- embedding: enhanced,
432
- relatedNodes,
433
- pathways,
434
- };
435
- }
436
- }
437
- }
438
- catch (e) {
439
- console.warn('[GNNService] Heterogeneous graph processing failed, falling back:', e);
440
- }
441
- }
442
- // JS fallback: direct neighbor aggregation
443
- const neighbors = graph.edges
444
- .filter(e => e.from === queryNodeId)
445
- .map(e => nodeMap.get(e.to))
446
- .filter(n => n !== undefined);
447
- const avgEmbedding = new Float32Array(queryNode.embedding.length);
448
- for (let i = 0; i < avgEmbedding.length; i++) {
449
- avgEmbedding[i] = queryNode.embedding[i];
450
- for (const neighbor of neighbors) {
451
- avgEmbedding[i] += neighbor.embedding[i] / (neighbors.length + 1);
452
- }
453
- }
454
- const relatedNodes = graph.nodes
455
- .filter(n => n.id !== queryNodeId)
456
- .map(n => ({
457
- id: n.id,
458
- type: n.type,
459
- relevance: this.cosineSim(avgEmbedding, n.embedding),
460
- }))
461
- .sort((a, b) => b.relevance - a.relevance)
462
- .slice(0, 10);
463
- const pathways = this.findStrongPathways(graph, queryNodeId, relatedNodes.slice(0, 5));
464
- return {
465
- embedding: avgEmbedding,
466
- relatedNodes,
467
- pathways,
468
- };
469
- }
470
- /**
471
- * Node classification for task categorization.
472
- *
473
- * Classifies nodes into predefined categories using GNN-based features.
474
- */
475
- async classifyNode(nodeEmbedding, neighborEmbeddings, categories) {
476
- if (!this.initialized)
477
- await this.initialize();
478
- if (this.engineType === 'native' && this.gnn && typeof this.gnn.forward === 'function') {
479
- try {
480
- const enhanced = this.gnn.forward(nodeEmbedding, neighborEmbeddings, neighborEmbeddings.map(() => 1.0));
481
- if (enhanced && enhanced.length >= categories.length) {
482
- // Use first N dimensions as category logits
483
- const logits = Array.from(enhanced.slice(0, categories.length));
484
- const expLogits = logits.map((l) => Math.exp(l));
485
- const expSum = expLogits.reduce((s, v) => s + v, 1e-10);
486
- const probs = expLogits.map(e => e / expSum);
487
- let maxIdx = 0;
488
- for (let i = 1; i < probs.length; i++) {
489
- if (probs[i] > probs[maxIdx])
490
- maxIdx = i;
491
- }
492
- const scores = {};
493
- categories.forEach((cat, i) => {
494
- scores[cat] = probs[i];
495
- });
496
- return {
497
- category: categories[maxIdx],
498
- confidence: probs[maxIdx],
499
- scores,
500
- };
501
- }
502
- }
503
- catch (e) {
504
- console.warn('[GNNService] Node classification failed, falling back:', e);
505
- }
506
- }
507
- // JS fallback: random with slight bias
508
- const scores = {};
509
- const probs = categories.map(() => Math.random());
510
- const sum = probs.reduce((s, v) => s + v, 0);
511
- const normalized = probs.map(p => p / sum);
512
- let maxIdx = 0;
513
- categories.forEach((cat, i) => {
514
- scores[cat] = normalized[i];
515
- if (normalized[i] > normalized[maxIdx])
516
- maxIdx = i;
517
- });
518
- return {
519
- category: categories[maxIdx],
520
- confidence: normalized[maxIdx],
521
- scores,
522
- };
523
- }
524
- /**
525
- * Link prediction for workflow optimization.
526
- *
527
- * Predicts likely connections between nodes to suggest workflow improvements.
528
- */
529
- async predictLinks(sourceNode, candidateNodes, existingEdges, topK = 5) {
530
- if (!this.initialized)
531
- await this.initialize();
532
- if (this.engineType === 'native' && this.gnn && typeof this.gnn.forward === 'function') {
533
- try {
534
- const enhanced = this.gnn.forward(sourceNode.embedding, candidateNodes.map(n => n.embedding), candidateNodes.map(() => 1.0));
535
- if (enhanced) {
536
- const predictions = candidateNodes.map(node => {
537
- // Check if edge already exists
538
- const exists = existingEdges.some(e => e.from === sourceNode.id && e.to === node.id);
539
- if (exists) {
540
- return { targetId: node.id, probability: 0, reasoning: 'Edge already exists' };
541
- }
542
- const similarity = this.cosineSim(enhanced, node.embedding);
543
- const probability = 1 / (1 + Math.exp(-5 * (similarity - 0.5))); // Sigmoid scaling
544
- let reasoning = 'Strong structural similarity';
545
- if (probability > 0.8)
546
- reasoning = 'Very high compatibility detected';
547
- else if (probability > 0.6)
548
- reasoning = 'Good potential for connection';
549
- else if (probability > 0.4)
550
- reasoning = 'Moderate connection potential';
551
- else
552
- reasoning = 'Weak connection likelihood';
553
- return { targetId: node.id, probability, reasoning };
554
- });
555
- return predictions
556
- .filter(p => p.probability > 0)
557
- .sort((a, b) => b.probability - a.probability)
558
- .slice(0, topK);
559
- }
560
- }
561
- catch (e) {
562
- console.warn('[GNNService] Link prediction failed, falling back:', e);
563
- }
564
- }
565
- // JS fallback: cosine similarity based
566
- return candidateNodes
567
- .map(node => {
568
- const exists = existingEdges.some(e => e.from === sourceNode.id && e.to === node.id);
569
- if (exists) {
570
- return { targetId: node.id, probability: 0, reasoning: 'Edge already exists' };
571
- }
572
- const similarity = this.cosineSim(sourceNode.embedding, node.embedding);
573
- return {
574
- targetId: node.id,
575
- probability: similarity,
576
- reasoning: similarity > 0.7 ? 'High similarity' : 'Moderate similarity',
577
- };
578
- })
579
- .filter(p => p.probability > 0)
580
- .sort((a, b) => b.probability - a.probability)
581
- .slice(0, topK);
582
- }
583
- // ---------------------------------------------------------------------------
584
- // Private
585
- // ---------------------------------------------------------------------------
586
- findStrongPathways(graph, startNodeId, targetNodes) {
587
- const pathways = [];
588
- for (const target of targetNodes) {
589
- // Simple BFS to find shortest path
590
- const visited = new Set();
591
- const queue = [
592
- { nodeId: startNodeId, path: [startNodeId] },
593
- ];
594
- while (queue.length > 0) {
595
- const current = queue.shift();
596
- if (current.nodeId === target.id) {
597
- // Calculate pathway strength
598
- let strength = target.relevance;
599
- for (let i = 0; i < current.path.length - 1; i++) {
600
- const edge = graph.edges.find(e => e.from === current.path[i] && e.to === current.path[i + 1]);
601
- strength *= edge?.weight || 0.5;
602
- }
603
- pathways.push({ path: current.path, strength });
604
- break;
605
- }
606
- if (visited.has(current.nodeId) || current.path.length > 4) {
607
- continue;
608
- }
609
- visited.add(current.nodeId);
610
- const neighbors = graph.edges
611
- .filter(e => e.from === current.nodeId)
612
- .map(e => e.to);
613
- for (const neighbor of neighbors) {
614
- if (!visited.has(neighbor)) {
615
- queue.push({
616
- nodeId: neighbor,
617
- path: [...current.path, neighbor],
618
- });
619
- }
620
- }
621
- }
622
- }
623
- return pathways.sort((a, b) => b.strength - a.strength).slice(0, 5);
624
- }
625
- cosineSim(a, b) {
626
- let dot = 0;
627
- let normA = 0;
628
- let normB = 0;
629
- const len = Math.min(a.length, b.length);
630
- for (let i = 0; i < len; i++) {
631
- dot += a[i] * b[i];
632
- normA += a[i] * a[i];
633
- normB += b[i] * b[i];
634
- }
635
- const denom = Math.sqrt(normA) * Math.sqrt(normB);
636
- return denom > 0 ? dot / denom : 0;
637
- }
638
- }
639
- //# sourceMappingURL=GNNService.js.map