@unrdf/knowledge-engine 5.0.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/package.json +64 -0
  4. package/src/browser-shims.mjs +343 -0
  5. package/src/browser.mjs +910 -0
  6. package/src/canonicalize.mjs +414 -0
  7. package/src/condition-cache.mjs +109 -0
  8. package/src/condition-evaluator.mjs +722 -0
  9. package/src/dark-matter-core.mjs +742 -0
  10. package/src/define-hook.mjs +213 -0
  11. package/src/effect-sandbox-browser.mjs +283 -0
  12. package/src/effect-sandbox-worker.mjs +170 -0
  13. package/src/effect-sandbox.mjs +517 -0
  14. package/src/engines/index.mjs +11 -0
  15. package/src/engines/rdf-engine.mjs +299 -0
  16. package/src/file-resolver.mjs +387 -0
  17. package/src/hook-executor-batching.mjs +277 -0
  18. package/src/hook-executor.mjs +870 -0
  19. package/src/hook-management.mjs +150 -0
  20. package/src/index.mjs +93 -0
  21. package/src/ken-parliment.mjs +119 -0
  22. package/src/ken.mjs +149 -0
  23. package/src/knowledge-engine/builtin-rules.mjs +190 -0
  24. package/src/knowledge-engine/inference-engine.mjs +418 -0
  25. package/src/knowledge-engine/knowledge-engine.mjs +317 -0
  26. package/src/knowledge-engine/pattern-dsl.mjs +142 -0
  27. package/src/knowledge-engine/pattern-matcher.mjs +215 -0
  28. package/src/knowledge-engine/rules.mjs +184 -0
  29. package/src/knowledge-engine.mjs +319 -0
  30. package/src/knowledge-hook-engine.mjs +360 -0
  31. package/src/knowledge-hook-manager.mjs +469 -0
  32. package/src/knowledge-substrate-core.mjs +927 -0
  33. package/src/lite.mjs +222 -0
  34. package/src/lockchain-writer-browser.mjs +414 -0
  35. package/src/lockchain-writer.mjs +602 -0
  36. package/src/monitoring/andon-signals.mjs +775 -0
  37. package/src/observability.mjs +531 -0
  38. package/src/parse.mjs +290 -0
  39. package/src/performance-optimizer.mjs +678 -0
  40. package/src/policy-pack.mjs +572 -0
  41. package/src/query-cache.mjs +116 -0
  42. package/src/query-optimizer.mjs +1051 -0
  43. package/src/query.mjs +306 -0
  44. package/src/reason.mjs +350 -0
  45. package/src/resolution-layer.mjs +506 -0
  46. package/src/schemas.mjs +1063 -0
  47. package/src/security/error-sanitizer.mjs +257 -0
  48. package/src/security/path-validator.mjs +194 -0
  49. package/src/security/sandbox-restrictions.mjs +331 -0
  50. package/src/security-validator.mjs +389 -0
  51. package/src/store-cache.mjs +137 -0
  52. package/src/telemetry.mjs +167 -0
  53. package/src/transaction.mjs +810 -0
  54. package/src/utils/adaptive-monitor.mjs +746 -0
  55. package/src/utils/circuit-breaker.mjs +513 -0
  56. package/src/utils/edge-case-handler.mjs +503 -0
  57. package/src/utils/memory-manager.mjs +498 -0
  58. package/src/utils/ring-buffer.mjs +282 -0
  59. package/src/validate.mjs +319 -0
  60. package/src/validators/index.mjs +338 -0
@@ -0,0 +1,506 @@
1
+ /**
2
+ * @file Resolution Layer for Multi-Agent Coordination
3
+ * @module resolution-layer
4
+ *
5
+ * @description
6
+ * Implements multi-agent coordination and Delta resolution for swarm behavior.
7
+ * Handles competing proposals from multiple agents and resolves them into
8
+ * a single, consolidated Delta.
9
+ */
10
+
11
+ import { randomUUID } from 'crypto';
12
+ import { z } from 'zod';
13
+
14
+ /**
15
+ * Schema for agent proposal
16
+ */
17
+ const AgentProposalSchema = z.object({
18
+ id: z.string().uuid(),
19
+ agentId: z.string().min(1),
20
+ delta: z.object({
21
+ additions: z.array(z.any()),
22
+ removals: z.array(z.any()),
23
+ metadata: z.record(z.any()).optional(),
24
+ }),
25
+ confidence: z.number().min(0).max(1),
26
+ priority: z.number().int().min(0).max(100).default(50),
27
+ timestamp: z.number(),
28
+ metadata: z.record(z.any()).optional(),
29
+ dependencies: z.array(z.string()).optional(),
30
+ conflicts: z.array(z.string()).optional(),
31
+ });
32
+
33
+ /**
34
+ * Schema for resolution strategy
35
+ */
36
+ const ResolutionStrategySchema = z.object({
37
+ type: z.enum(['voting', 'merging', 'crdt', 'consensus', 'priority', 'random']),
38
+ parameters: z.record(z.any()).optional(),
39
+ timeout: z.number().int().positive().max(300000).default(30000),
40
+ quorum: z.number().min(0).max(1).default(0.5),
41
+ maxRetries: z.number().int().nonnegative().max(10).default(3),
42
+ });
43
+
44
+ /**
45
+ * Schema for resolution result
46
+ */
47
+ const ResolutionResultSchema = z.object({
48
+ id: z.string().uuid(),
49
+ strategy: z.string(),
50
+ proposals: z.array(AgentProposalSchema),
51
+ resolvedDelta: z.object({
52
+ additions: z.array(z.any()),
53
+ removals: z.array(z.any()),
54
+ metadata: z.record(z.any()).optional(),
55
+ }),
56
+ confidence: z.number().min(0).max(1),
57
+ consensus: z.boolean(),
58
+ conflicts: z
59
+ .array(
60
+ z.object({
61
+ type: z.enum(['addition', 'removal', 'metadata']),
62
+ proposals: z.array(z.string()),
63
+ resolution: z.string(),
64
+ })
65
+ )
66
+ .optional(),
67
+ timestamp: z.number(),
68
+ duration: z.number().nonnegative(),
69
+ });
70
+
71
+ /**
72
+ * Resolution Layer for multi-agent coordination
73
+ */
74
+ export class ResolutionLayer {
75
+ /**
76
+ * Create a new resolution layer
77
+ * @param {Object} [config] - Configuration
78
+ */
79
+ constructor(config = {}) {
80
+ this.config = {
81
+ defaultStrategy: config.defaultStrategy || 'voting',
82
+ maxProposals: config.maxProposals || 100,
83
+ enableConflictDetection: config.enableConflictDetection !== false,
84
+ enableConsensus: config.enableConsensus !== false,
85
+ timeout: config.timeout || 30000,
86
+ ...config,
87
+ };
88
+
89
+ this.proposals = new Map();
90
+ this.resolutionHistory = [];
91
+ this.agents = new Map();
92
+ this.strategies = new Map();
93
+
94
+ // Register default strategies
95
+ this._registerDefaultStrategies();
96
+ }
97
+
98
+ /**
99
+ * Register an agent
100
+ * @param {string} agentId - Agent identifier
101
+ * @param {Object} [metadata] - Agent metadata
102
+ */
103
+ registerAgent(agentId, metadata = {}) {
104
+ this.agents.set(agentId, {
105
+ id: agentId,
106
+ metadata,
107
+ registeredAt: Date.now(),
108
+ proposalCount: 0,
109
+ lastActivity: Date.now(),
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Submit a proposal from an agent
115
+ * @param {string} agentId - Agent identifier
116
+ * @param {Object} delta - Proposed delta
117
+ * @param {Object} [options] - Proposal options
118
+ * @returns {Promise<string>} Proposal ID
119
+ */
120
+ async submitProposal(agentId, delta, options = {}) {
121
+ // Validate agent
122
+ if (!this.agents.has(agentId)) {
123
+ this.registerAgent(agentId);
124
+ }
125
+
126
+ const proposal = {
127
+ id: randomUUID(),
128
+ agentId,
129
+ delta,
130
+ confidence: options.confidence || 0.5,
131
+ priority: options.priority || 50,
132
+ timestamp: Date.now(),
133
+ metadata: options.metadata || {},
134
+ dependencies: options.dependencies || [],
135
+ conflicts: options.conflicts || [],
136
+ };
137
+
138
+ // Validate proposal
139
+ const validatedProposal = AgentProposalSchema.parse(proposal);
140
+
141
+ // Store proposal
142
+ this.proposals.set(validatedProposal.id, validatedProposal);
143
+
144
+ // Update agent stats
145
+ const agent = this.agents.get(agentId);
146
+ agent.proposalCount++;
147
+ agent.lastActivity = Date.now();
148
+
149
+ return validatedProposal.id;
150
+ }
151
+
152
+ /**
153
+ * Resolve proposals using specified strategy
154
+ * @param {Array<string>} proposalIds - Proposal IDs to resolve
155
+ * @param {Object} [strategy] - Resolution strategy
156
+ * @returns {Promise<Object>} Resolution result
157
+ */
158
+ async resolveProposals(proposalIds, strategy = {}) {
159
+ const startTime = Date.now();
160
+ const resolutionId = randomUUID();
161
+
162
+ try {
163
+ // Get proposals
164
+ const proposals = proposalIds.map(id => this.proposals.get(id)).filter(p => p !== undefined);
165
+
166
+ if (proposals.length === 0) {
167
+ throw new Error('No valid proposals found');
168
+ }
169
+
170
+ // Validate strategy
171
+ const validatedStrategy = ResolutionStrategySchema.parse({
172
+ type: strategy.type || this.config.defaultStrategy,
173
+ parameters: strategy.parameters || {},
174
+ timeout: strategy.timeout || this.config.timeout,
175
+ quorum: strategy.quorum || 0.5,
176
+ maxRetries: strategy.maxRetries || 3,
177
+ });
178
+
179
+ // Get resolution function
180
+ const resolutionFn = this.strategies.get(validatedStrategy.type);
181
+ if (!resolutionFn) {
182
+ throw new Error(`Unknown resolution strategy: ${validatedStrategy.type}`);
183
+ }
184
+
185
+ // Resolve proposals
186
+ const resolvedDelta = await resolutionFn(proposals, validatedStrategy);
187
+
188
+ // Calculate consensus
189
+ const consensus = this._calculateConsensus(proposals, resolvedDelta);
190
+
191
+ // Detect conflicts
192
+ const conflicts = this.config.enableConflictDetection
193
+ ? this._detectConflicts(proposals, resolvedDelta)
194
+ : [];
195
+
196
+ const result = {
197
+ id: resolutionId,
198
+ strategy: validatedStrategy.type,
199
+ proposals,
200
+ resolvedDelta,
201
+ confidence: this._calculateConfidence(proposals, resolvedDelta),
202
+ consensus,
203
+ conflicts,
204
+ timestamp: Date.now(),
205
+ duration: Date.now() - startTime,
206
+ };
207
+
208
+ // Validate result
209
+ const validatedResult = ResolutionResultSchema.parse(result);
210
+
211
+ // Store in history
212
+ this.resolutionHistory.push(validatedResult);
213
+
214
+ return validatedResult;
215
+ } catch (error) {
216
+ throw new Error(`Resolution failed: ${error.message}`);
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Get all proposals for an agent
222
+ * @param {string} agentId - Agent identifier
223
+ * @returns {Array} Agent proposals
224
+ */
225
+ getAgentProposals(agentId) {
226
+ return Array.from(this.proposals.values()).filter(p => p.agentId === agentId);
227
+ }
228
+
229
+ /**
230
+ * Get all active proposals
231
+ * @returns {Array} All proposals
232
+ */
233
+ getAllProposals() {
234
+ return Array.from(this.proposals.values());
235
+ }
236
+
237
+ /**
238
+ * Get resolution history
239
+ * @param {number} [limit] - Limit number of results
240
+ * @returns {Array} Resolution history
241
+ */
242
+ getResolutionHistory(limit) {
243
+ const history = [...this.resolutionHistory].reverse();
244
+ return limit ? history.slice(0, limit) : history;
245
+ }
246
+
247
+ /**
248
+ * Get layer statistics
249
+ * @returns {Object} Statistics
250
+ */
251
+ getStats() {
252
+ const proposals = Array.from(this.proposals.values());
253
+ const agents = Array.from(this.agents.values());
254
+
255
+ return {
256
+ config: this.config,
257
+ proposals: {
258
+ total: proposals.length,
259
+ byAgent: agents.reduce((acc, agent) => {
260
+ acc[agent.id] = agent.proposalCount;
261
+ return acc;
262
+ }, {}),
263
+ },
264
+ agents: {
265
+ total: agents.length,
266
+ active: agents.filter(a => Date.now() - a.lastActivity < 300000).length, // 5 minutes
267
+ },
268
+ resolutions: {
269
+ total: this.resolutionHistory.length,
270
+ strategies: this.resolutionHistory.reduce((acc, r) => {
271
+ acc[r.strategy] = (acc[r.strategy] || 0) + 1;
272
+ return acc;
273
+ }, {}),
274
+ },
275
+ };
276
+ }
277
+
278
+ /**
279
+ * Register default resolution strategies
280
+ * @private
281
+ */
282
+ _registerDefaultStrategies() {
283
+ // Voting strategy
284
+ this.strategies.set('voting', async (proposals, _strategy) => {
285
+ const votes = new Map();
286
+
287
+ for (const proposal of proposals) {
288
+ const weight = proposal.confidence * (proposal.priority / 100);
289
+ const key = JSON.stringify(proposal.delta);
290
+ votes.set(key, (votes.get(key) || 0) + weight);
291
+ }
292
+
293
+ // Find highest voted delta
294
+ let bestDelta = null;
295
+ let bestWeight = 0;
296
+
297
+ for (const [deltaKey, weight] of votes) {
298
+ if (weight > bestWeight) {
299
+ bestWeight = weight;
300
+ bestDelta = JSON.parse(deltaKey);
301
+ }
302
+ }
303
+
304
+ return bestDelta;
305
+ });
306
+
307
+ // Merging strategy
308
+ this.strategies.set('merging', async (proposals, _strategy) => {
309
+ const merged = { additions: [], removals: [], metadata: {} };
310
+
311
+ for (const proposal of proposals) {
312
+ merged.additions.push(...proposal.delta.additions);
313
+ merged.removals.push(...proposal.delta.removals);
314
+ Object.assign(merged.metadata, proposal.delta.metadata || {});
315
+ }
316
+
317
+ // Remove duplicates
318
+ merged.additions = this._deduplicateQuads(merged.additions);
319
+ merged.removals = this._deduplicateQuads(merged.removals);
320
+
321
+ return merged;
322
+ });
323
+
324
+ // Priority strategy
325
+ this.strategies.set('priority', async (proposals, _strategy) => {
326
+ const sorted = proposals.sort((a, b) => b.priority - a.priority);
327
+ return sorted[0].delta;
328
+ });
329
+
330
+ // Random strategy
331
+ this.strategies.set('random', async (proposals, _strategy) => {
332
+ const randomIndex = Math.floor(Math.random() * proposals.length);
333
+ return proposals[randomIndex].delta;
334
+ });
335
+
336
+ // CRDT strategy (simplified)
337
+ this.strategies.set('crdt', async (proposals, _strategy) => {
338
+ const crdt = { additions: new Map(), removals: new Map() };
339
+
340
+ for (const proposal of proposals) {
341
+ // Add additions with timestamps
342
+ for (const quad of proposal.delta.additions) {
343
+ const key = this._quadToKey(quad);
344
+ const existing = crdt.additions.get(key);
345
+ if (!existing || proposal.timestamp > existing.timestamp) {
346
+ crdt.additions.set(key, {
347
+ quad,
348
+ timestamp: proposal.timestamp,
349
+ agent: proposal.agentId,
350
+ });
351
+ }
352
+ }
353
+
354
+ // Add removals with timestamps
355
+ for (const quad of proposal.delta.removals) {
356
+ const key = this._quadToKey(quad);
357
+ const existing = crdt.removals.get(key);
358
+ if (!existing || proposal.timestamp > existing.timestamp) {
359
+ crdt.removals.set(key, {
360
+ quad,
361
+ timestamp: proposal.timestamp,
362
+ agent: proposal.agentId,
363
+ });
364
+ }
365
+ }
366
+ }
367
+
368
+ return {
369
+ additions: Array.from(crdt.additions.values()).map(v => v.quad),
370
+ removals: Array.from(crdt.removals.values()).map(v => v.quad),
371
+ metadata: { strategy: 'crdt', timestamp: Date.now() },
372
+ };
373
+ });
374
+ }
375
+
376
+ /**
377
+ * Calculate consensus
378
+ * @param {Array} proposals - Proposals
379
+ * @param {Object} resolvedDelta - Resolved delta
380
+ * @returns {boolean} Consensus achieved
381
+ * @private
382
+ */
383
+ _calculateConsensus(proposals, resolvedDelta) {
384
+ if (proposals.length === 0) return false;
385
+
386
+ const resolvedKey = JSON.stringify(resolvedDelta);
387
+ let consensusCount = 0;
388
+
389
+ for (const proposal of proposals) {
390
+ const proposalKey = JSON.stringify(proposal.delta);
391
+ if (proposalKey === resolvedKey) {
392
+ consensusCount++;
393
+ }
394
+ }
395
+
396
+ const consensusRatio = consensusCount / proposals.length;
397
+ return consensusRatio >= 0.5; // 50% consensus threshold
398
+ }
399
+
400
+ /**
401
+ * Detect conflicts between proposals
402
+ * @param {Array} proposals - Proposals
403
+ * @param {Object} resolvedDelta - Resolved delta
404
+ * @returns {Array} Conflicts
405
+ * @private
406
+ */
407
+ _detectConflicts(proposals, resolvedDelta) {
408
+ const conflicts = [];
409
+
410
+ // Check for conflicting additions/removals
411
+ const resolvedAdditions = new Set(resolvedDelta.additions.map(q => this._quadToKey(q)));
412
+ const resolvedRemovals = new Set(resolvedDelta.removals.map(q => this._quadToKey(q)));
413
+
414
+ for (const proposal of proposals) {
415
+ const proposalAdditions = new Set(proposal.delta.additions.map(q => this._quadToKey(q)));
416
+ const proposalRemovals = new Set(proposal.delta.removals.map(q => this._quadToKey(q)));
417
+
418
+ // Check for conflicts
419
+ for (const key of proposalAdditions) {
420
+ if (resolvedRemovals.has(key)) {
421
+ conflicts.push({
422
+ type: 'addition',
423
+ proposals: [proposal.id],
424
+ resolution: 'conflict detected',
425
+ });
426
+ }
427
+ }
428
+
429
+ for (const key of proposalRemovals) {
430
+ if (resolvedAdditions.has(key)) {
431
+ conflicts.push({
432
+ type: 'removal',
433
+ proposals: [proposal.id],
434
+ resolution: 'conflict detected',
435
+ });
436
+ }
437
+ }
438
+ }
439
+
440
+ return conflicts;
441
+ }
442
+
443
+ /**
444
+ * Calculate confidence score
445
+ * @param {Array} proposals - Proposals
446
+ * @param {Object} resolvedDelta - Resolved delta
447
+ * @returns {number} Confidence score
448
+ * @private
449
+ */
450
+ _calculateConfidence(proposals, _resolvedDelta) {
451
+ if (proposals.length === 0) return 0;
452
+
453
+ let totalConfidence = 0;
454
+ let weightSum = 0;
455
+
456
+ for (const proposal of proposals) {
457
+ const weight = proposal.priority / 100;
458
+ totalConfidence += proposal.confidence * weight;
459
+ weightSum += weight;
460
+ }
461
+
462
+ return weightSum > 0 ? totalConfidence / weightSum : 0;
463
+ }
464
+
465
+ /**
466
+ * Deduplicate quads
467
+ * @param {Array} quads - Quads array
468
+ * @returns {Array} Deduplicated quads
469
+ * @private
470
+ */
471
+ _deduplicateQuads(quads) {
472
+ const seen = new Set();
473
+ return quads.filter(quad => {
474
+ const key = this._quadToKey(quad);
475
+ if (seen.has(key)) {
476
+ return false;
477
+ }
478
+ seen.add(key);
479
+ return true;
480
+ });
481
+ }
482
+
483
+ /**
484
+ * Convert quad to key
485
+ * @param {Object} quad - RDF quad
486
+ * @returns {string} Quad key
487
+ * @private
488
+ */
489
+ _quadToKey(quad) {
490
+ return `${quad.subject?.value || ''}:${quad.predicate?.value || ''}:${quad.object?.value || ''}:${quad.graph?.value || ''}`;
491
+ }
492
+ }
493
+
494
+ /**
495
+ * Create a resolution layer instance
496
+ * @param {Object} [config] - Configuration
497
+ * @returns {ResolutionLayer} Resolution layer
498
+ */
499
+ export function createResolutionLayer(config = {}) {
500
+ return new ResolutionLayer(config);
501
+ }
502
+
503
+ /**
504
+ * Default resolution layer instance
505
+ */
506
+ export const defaultResolutionLayer = createResolutionLayer();