@unrdf/knowledge-engine 5.0.1 → 26.4.3

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 (71) hide show
  1. package/package.json +13 -7
  2. package/src/ai-enhanced-search.mjs +371 -0
  3. package/src/anomaly-detector.mjs +226 -0
  4. package/src/artifact-generator.mjs +251 -0
  5. package/src/browser.mjs +1 -1
  6. package/src/chatman/disruption-arithmetic.mjs +140 -0
  7. package/src/chatman/market-dynamics.mjs +140 -0
  8. package/src/chatman/organizational-dynamics.mjs +140 -0
  9. package/src/chatman/strategic-dynamics.mjs +140 -0
  10. package/src/chatman-config-loader.mjs +282 -0
  11. package/src/chatman-engine.mjs +431 -0
  12. package/src/chatman-operator.mjs +342 -0
  13. package/src/dark-field-detector.mjs +312 -0
  14. package/src/formation-theorems.mjs +345 -0
  15. package/src/index.mjs +20 -2
  16. package/src/knowledge-hook-manager.mjs +1 -1
  17. package/src/lockchain-writer-browser.mjs +2 -2
  18. package/src/observability.mjs +40 -4
  19. package/src/query-optimizer.mjs +1 -1
  20. package/src/resolution-layer.mjs +1 -1
  21. package/src/transaction.mjs +11 -9
  22. package/README.md +0 -84
  23. package/src/browser-shims.mjs +0 -343
  24. package/src/canonicalize.mjs +0 -414
  25. package/src/condition-cache.mjs +0 -109
  26. package/src/condition-evaluator.mjs +0 -722
  27. package/src/dark-matter-core.mjs +0 -742
  28. package/src/define-hook.mjs +0 -213
  29. package/src/effect-sandbox-browser.mjs +0 -283
  30. package/src/effect-sandbox-worker.mjs +0 -170
  31. package/src/effect-sandbox.mjs +0 -517
  32. package/src/engines/index.mjs +0 -11
  33. package/src/engines/rdf-engine.mjs +0 -299
  34. package/src/file-resolver.mjs +0 -387
  35. package/src/hook-executor-batching.mjs +0 -277
  36. package/src/hook-executor.mjs +0 -870
  37. package/src/hook-management.mjs +0 -150
  38. package/src/ken-parliment.mjs +0 -119
  39. package/src/ken.mjs +0 -149
  40. package/src/knowledge-engine/builtin-rules.mjs +0 -190
  41. package/src/knowledge-engine/inference-engine.mjs +0 -418
  42. package/src/knowledge-engine/knowledge-engine.mjs +0 -317
  43. package/src/knowledge-engine/pattern-dsl.mjs +0 -142
  44. package/src/knowledge-engine/pattern-matcher.mjs +0 -215
  45. package/src/knowledge-engine/rules.mjs +0 -184
  46. package/src/knowledge-engine.mjs +0 -319
  47. package/src/knowledge-hook-engine.mjs +0 -360
  48. package/src/knowledge-substrate-core.mjs +0 -927
  49. package/src/lite.mjs +0 -222
  50. package/src/lockchain-writer.mjs +0 -602
  51. package/src/monitoring/andon-signals.mjs +0 -775
  52. package/src/parse.mjs +0 -290
  53. package/src/performance-optimizer.mjs +0 -678
  54. package/src/policy-pack.mjs +0 -572
  55. package/src/query-cache.mjs +0 -116
  56. package/src/query.mjs +0 -306
  57. package/src/reason.mjs +0 -350
  58. package/src/schemas.mjs +0 -1063
  59. package/src/security/error-sanitizer.mjs +0 -257
  60. package/src/security/path-validator.mjs +0 -194
  61. package/src/security/sandbox-restrictions.mjs +0 -331
  62. package/src/security-validator.mjs +0 -389
  63. package/src/store-cache.mjs +0 -137
  64. package/src/telemetry.mjs +0 -167
  65. package/src/utils/adaptive-monitor.mjs +0 -746
  66. package/src/utils/circuit-breaker.mjs +0 -513
  67. package/src/utils/edge-case-handler.mjs +0 -503
  68. package/src/utils/memory-manager.mjs +0 -498
  69. package/src/utils/ring-buffer.mjs +0 -282
  70. package/src/validate.mjs +0 -319
  71. package/src/validators/index.mjs +0 -338
@@ -1,513 +0,0 @@
1
- /**
2
- * @file Circuit Breaker Pattern for Fault Tolerance
3
- * @module knowledge-engine/utils/circuit-breaker
4
- *
5
- * @description
6
- * Implements the circuit breaker pattern for fault tolerance in distributed
7
- * operations like federation, remote SPARQL endpoints, and external services.
8
- *
9
- * States:
10
- * - CLOSED: Normal operation, requests pass through
11
- * - OPEN: Circuit tripped, requests fail immediately
12
- * - HALF_OPEN: Testing if service recovered
13
- */
14
-
15
- import { trace, SpanStatusCode } from '@opentelemetry/api';
16
-
17
- /**
18
- * Circuit breaker states
19
- * @readonly
20
- * @enum {string}
21
- */
22
- export const CircuitState = Object.freeze({
23
- CLOSED: 'closed',
24
- OPEN: 'open',
25
- HALF_OPEN: 'half_open',
26
- });
27
-
28
- /**
29
- * Circuit breaker configuration schema
30
- * @typedef {Object} CircuitBreakerConfig
31
- * @property {number} [failureThreshold=5] - Failures before opening circuit
32
- * @property {number} [resetTimeout=30000] - Time in ms before trying half-open
33
- * @property {number} [halfOpenMaxCalls=3] - Max calls in half-open state
34
- * @property {number} [successThreshold=2] - Successes in half-open to close
35
- * @property {string} [name='circuit-breaker'] - Name for tracing
36
- * @property {Function} [onStateChange] - Callback on state transitions
37
- * @property {Function} [isFailure] - Custom failure detection function
38
- */
39
-
40
- /**
41
- * Circuit breaker for fault tolerance
42
- *
43
- * @example
44
- * const breaker = new CircuitBreaker({
45
- * failureThreshold: 5,
46
- * resetTimeout: 30000,
47
- * name: 'sparql-endpoint'
48
- * });
49
- *
50
- * try {
51
- * const result = await breaker.execute(() => fetch(sparqlEndpoint));
52
- * } catch (error) {
53
- * if (error.name === 'CircuitOpenError') {
54
- * // Circuit is open, use cached data
55
- * }
56
- * }
57
- */
58
- export class CircuitBreaker {
59
- /**
60
- * Create a new circuit breaker
61
- * @param {CircuitBreakerConfig} [config={}] - Configuration options
62
- */
63
- constructor(config = {}) {
64
- this.state = CircuitState.CLOSED;
65
- this.failureCount = 0;
66
- this.successCount = 0;
67
- this.halfOpenCalls = 0;
68
- this.lastFailureTime = null;
69
- this.lastStateChange = Date.now();
70
-
71
- // Configuration with defaults
72
- this.failureThreshold = config.failureThreshold ?? 5;
73
- this.resetTimeout = config.resetTimeout ?? 30000;
74
- this.halfOpenMaxCalls = config.halfOpenMaxCalls ?? 3;
75
- this.successThreshold = config.successThreshold ?? 2;
76
- this.name = config.name ?? 'circuit-breaker';
77
- this.onStateChange = config.onStateChange ?? null;
78
- this.isFailure = config.isFailure ?? (_error => true);
79
-
80
- // Metrics
81
- this.metrics = {
82
- totalCalls: 0,
83
- successfulCalls: 0,
84
- failedCalls: 0,
85
- rejectedCalls: 0,
86
- stateChanges: 0,
87
- };
88
-
89
- // OTEL tracer
90
- this.tracer = trace.getTracer('unrdf-circuit-breaker');
91
- }
92
-
93
- /**
94
- * Execute a function with circuit breaker protection
95
- * @param {Function} fn - Async function to execute
96
- * @param {Object} [context={}] - Execution context for tracing
97
- * @returns {Promise<any>} Result of the function
98
- * @throws {CircuitOpenError} If circuit is open
99
- * @throws {Error} If function execution fails
100
- */
101
- async execute(fn, context = {}) {
102
- return await this.tracer.startActiveSpan(`circuit-breaker.${this.name}`, async span => {
103
- span.setAttributes({
104
- 'circuit.name': this.name,
105
- 'circuit.state': this.state,
106
- 'circuit.failure_count': this.failureCount,
107
- ...context,
108
- });
109
-
110
- this.metrics.totalCalls++;
111
-
112
- try {
113
- // Check if circuit should transition
114
- this._checkStateTransition();
115
-
116
- // Handle based on current state
117
- if (this.state === CircuitState.OPEN) {
118
- this.metrics.rejectedCalls++;
119
- span.setAttributes({
120
- 'circuit.rejected': true,
121
- 'circuit.reason': 'circuit_open',
122
- });
123
- span.setStatus({
124
- code: SpanStatusCode.ERROR,
125
- message: 'Circuit is open',
126
- });
127
- throw new CircuitOpenError(
128
- `Circuit breaker '${this.name}' is open`,
129
- this.name,
130
- this.lastFailureTime
131
- );
132
- }
133
-
134
- if (this.state === CircuitState.HALF_OPEN) {
135
- if (this.halfOpenCalls >= this.halfOpenMaxCalls) {
136
- this.metrics.rejectedCalls++;
137
- span.setAttributes({
138
- 'circuit.rejected': true,
139
- 'circuit.reason': 'half_open_limit',
140
- });
141
- span.setStatus({
142
- code: SpanStatusCode.ERROR,
143
- message: 'Half-open call limit reached',
144
- });
145
- throw new CircuitOpenError(
146
- `Circuit breaker '${this.name}' half-open limit reached`,
147
- this.name,
148
- this.lastFailureTime
149
- );
150
- }
151
- this.halfOpenCalls++;
152
- }
153
-
154
- // Execute the function
155
- const result = await fn();
156
-
157
- // Record success
158
- this.recordSuccess();
159
- this.metrics.successfulCalls++;
160
- span.setAttributes({
161
- 'circuit.success': true,
162
- 'circuit.final_state': this.state,
163
- });
164
- span.setStatus({ code: SpanStatusCode.OK });
165
-
166
- return result;
167
- } catch (error) {
168
- // Check if this is a circuit error (pass through)
169
- if (error instanceof CircuitOpenError) {
170
- span.end();
171
- throw error;
172
- }
173
-
174
- // Determine if this error counts as a failure
175
- if (this.isFailure(error)) {
176
- this.recordFailure();
177
- this.metrics.failedCalls++;
178
- span.setAttributes({
179
- 'circuit.failure': true,
180
- 'circuit.final_state': this.state,
181
- 'circuit.error': error.message,
182
- });
183
- }
184
-
185
- span.recordException(error);
186
- span.setStatus({
187
- code: SpanStatusCode.ERROR,
188
- message: error.message,
189
- });
190
- throw error;
191
- } finally {
192
- span.end();
193
- }
194
- });
195
- }
196
-
197
- /**
198
- * Record a successful operation
199
- */
200
- recordSuccess() {
201
- if (this.state === CircuitState.HALF_OPEN) {
202
- this.successCount++;
203
- if (this.successCount >= this.successThreshold) {
204
- this.reset();
205
- }
206
- } else if (this.state === CircuitState.CLOSED) {
207
- // Reset failure count on success in closed state
208
- this.failureCount = 0;
209
- }
210
- }
211
-
212
- /**
213
- * Record a failed operation
214
- */
215
- recordFailure() {
216
- this.failureCount++;
217
- this.lastFailureTime = Date.now();
218
-
219
- if (this.state === CircuitState.HALF_OPEN) {
220
- // Any failure in half-open trips the circuit again
221
- this.trip();
222
- } else if (this.state === CircuitState.CLOSED) {
223
- if (this.failureCount >= this.failureThreshold) {
224
- this.trip();
225
- }
226
- }
227
- }
228
-
229
- /**
230
- * Trip the circuit breaker (open the circuit)
231
- */
232
- trip() {
233
- if (this.state !== CircuitState.OPEN) {
234
- const previousState = this.state;
235
- this.state = CircuitState.OPEN;
236
- this.lastStateChange = Date.now();
237
- this.metrics.stateChanges++;
238
-
239
- this._notifyStateChange(previousState, CircuitState.OPEN);
240
- }
241
- }
242
-
243
- /**
244
- * Reset the circuit breaker (close the circuit)
245
- */
246
- reset() {
247
- const previousState = this.state;
248
- this.state = CircuitState.CLOSED;
249
- this.failureCount = 0;
250
- this.successCount = 0;
251
- this.halfOpenCalls = 0;
252
- this.lastStateChange = Date.now();
253
- this.metrics.stateChanges++;
254
-
255
- this._notifyStateChange(previousState, CircuitState.CLOSED);
256
- }
257
-
258
- /**
259
- * Force the circuit into half-open state
260
- */
261
- halfOpen() {
262
- if (this.state !== CircuitState.HALF_OPEN) {
263
- const previousState = this.state;
264
- this.state = CircuitState.HALF_OPEN;
265
- this.successCount = 0;
266
- this.halfOpenCalls = 0;
267
- this.lastStateChange = Date.now();
268
- this.metrics.stateChanges++;
269
-
270
- this._notifyStateChange(previousState, CircuitState.HALF_OPEN);
271
- }
272
- }
273
-
274
- /**
275
- * Check if state should transition based on timeout
276
- * @private
277
- */
278
- _checkStateTransition() {
279
- if (this.state === CircuitState.OPEN) {
280
- const timeSinceOpen = Date.now() - this.lastStateChange;
281
- if (timeSinceOpen >= this.resetTimeout) {
282
- this.halfOpen();
283
- }
284
- }
285
- }
286
-
287
- /**
288
- * Notify state change callback
289
- * @param {string} from - Previous state
290
- * @param {string} to - New state
291
- * @private
292
- */
293
- _notifyStateChange(from, to) {
294
- if (this.onStateChange) {
295
- try {
296
- this.onStateChange({
297
- name: this.name,
298
- from,
299
- to,
300
- timestamp: Date.now(),
301
- failureCount: this.failureCount,
302
- metrics: { ...this.metrics },
303
- });
304
- } catch (error) {
305
- // Ignore callback errors
306
- }
307
- }
308
- }
309
-
310
- /**
311
- * Get current circuit breaker status
312
- * @returns {Object} Status object
313
- */
314
- getStatus() {
315
- return {
316
- name: this.name,
317
- state: this.state,
318
- failureCount: this.failureCount,
319
- successCount: this.successCount,
320
- halfOpenCalls: this.halfOpenCalls,
321
- lastFailureTime: this.lastFailureTime,
322
- lastStateChange: this.lastStateChange,
323
- config: {
324
- failureThreshold: this.failureThreshold,
325
- resetTimeout: this.resetTimeout,
326
- halfOpenMaxCalls: this.halfOpenMaxCalls,
327
- successThreshold: this.successThreshold,
328
- },
329
- metrics: { ...this.metrics },
330
- };
331
- }
332
-
333
- /**
334
- * Check if circuit is healthy (closed)
335
- * @returns {boolean} True if circuit is closed
336
- */
337
- isHealthy() {
338
- return this.state === CircuitState.CLOSED;
339
- }
340
-
341
- /**
342
- * Check if circuit is open
343
- * @returns {boolean} True if circuit is open
344
- */
345
- isOpen() {
346
- this._checkStateTransition();
347
- return this.state === CircuitState.OPEN;
348
- }
349
-
350
- /**
351
- * Check if circuit is half-open
352
- * @returns {boolean} True if circuit is half-open
353
- */
354
- isHalfOpen() {
355
- this._checkStateTransition();
356
- return this.state === CircuitState.HALF_OPEN;
357
- }
358
-
359
- /**
360
- * Reset metrics counters
361
- */
362
- resetMetrics() {
363
- this.metrics = {
364
- totalCalls: 0,
365
- successfulCalls: 0,
366
- failedCalls: 0,
367
- rejectedCalls: 0,
368
- stateChanges: 0,
369
- };
370
- }
371
- }
372
-
373
- /**
374
- * Error thrown when circuit is open
375
- */
376
- export class CircuitOpenError extends Error {
377
- /**
378
- * Create a circuit open error
379
- * @param {string} message - Error message
380
- * @param {string} circuitName - Name of the circuit
381
- * @param {number} lastFailureTime - Timestamp of last failure
382
- */
383
- constructor(message, circuitName, lastFailureTime) {
384
- super(message);
385
- this.name = 'CircuitOpenError';
386
- this.circuitName = circuitName;
387
- this.lastFailureTime = lastFailureTime;
388
- }
389
- }
390
-
391
- /**
392
- * Circuit breaker registry for managing multiple breakers
393
- */
394
- export class CircuitBreakerRegistry {
395
- /**
396
- *
397
- */
398
- constructor() {
399
- this.breakers = new Map();
400
- }
401
-
402
- /**
403
- * Get or create a circuit breaker
404
- * @param {string} name - Breaker name
405
- * @param {CircuitBreakerConfig} [config] - Config for new breaker
406
- * @returns {CircuitBreaker} Circuit breaker instance
407
- */
408
- getOrCreate(name, config = {}) {
409
- if (!this.breakers.has(name)) {
410
- this.breakers.set(name, new CircuitBreaker({ ...config, name }));
411
- }
412
- return this.breakers.get(name);
413
- }
414
-
415
- /**
416
- * Get an existing circuit breaker
417
- * @param {string} name - Breaker name
418
- * @returns {CircuitBreaker|undefined} Circuit breaker or undefined
419
- */
420
- get(name) {
421
- return this.breakers.get(name);
422
- }
423
-
424
- /**
425
- * Check if a breaker exists
426
- * @param {string} name - Breaker name
427
- * @returns {boolean} True if exists
428
- */
429
- has(name) {
430
- return this.breakers.has(name);
431
- }
432
-
433
- /**
434
- * Remove a circuit breaker
435
- * @param {string} name - Breaker name
436
- * @returns {boolean} True if removed
437
- */
438
- remove(name) {
439
- return this.breakers.delete(name);
440
- }
441
-
442
- /**
443
- * Get all circuit breaker statuses
444
- * @returns {Object} Map of name to status
445
- */
446
- getAllStatuses() {
447
- const statuses = {};
448
- for (const [name, breaker] of this.breakers) {
449
- statuses[name] = breaker.getStatus();
450
- }
451
- return statuses;
452
- }
453
-
454
- /**
455
- * Reset all circuit breakers
456
- */
457
- resetAll() {
458
- for (const breaker of this.breakers.values()) {
459
- breaker.reset();
460
- }
461
- }
462
-
463
- /**
464
- * Get health summary of all breakers
465
- * @returns {Object} Health summary
466
- */
467
- getHealthSummary() {
468
- let healthy = 0;
469
- let open = 0;
470
- let halfOpen = 0;
471
-
472
- for (const breaker of this.breakers.values()) {
473
- if (breaker.isHealthy()) healthy++;
474
- else if (breaker.isOpen()) open++;
475
- else if (breaker.isHalfOpen()) halfOpen++;
476
- }
477
-
478
- return {
479
- total: this.breakers.size,
480
- healthy,
481
- open,
482
- halfOpen,
483
- healthPercent: this.breakers.size > 0 ? (healthy / this.breakers.size) * 100 : 100,
484
- };
485
- }
486
- }
487
-
488
- /**
489
- * Default global registry
490
- */
491
- export const defaultRegistry = new CircuitBreakerRegistry();
492
-
493
- /**
494
- * Create a circuit breaker with default configuration
495
- * @param {string} name - Breaker name
496
- * @param {CircuitBreakerConfig} [config] - Configuration
497
- * @returns {CircuitBreaker} Circuit breaker instance
498
- */
499
- export function createCircuitBreaker(name, config = {}) {
500
- return new CircuitBreaker({ ...config, name });
501
- }
502
-
503
- /**
504
- * Decorator/wrapper function for adding circuit breaker to any async function
505
- * @param {Function} fn - Async function to wrap
506
- * @param {CircuitBreaker} breaker - Circuit breaker instance
507
- * @returns {Function} Wrapped function
508
- */
509
- export function withCircuitBreaker(fn, breaker) {
510
- return async function (...args) {
511
- return await breaker.execute(() => fn.apply(this, args));
512
- };
513
- }