@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @unrdf/knowledge-engine
2
+
3
+ ![Version](https://img.shields.io/badge/version-5.0.0--beta.1-blue) ![Production Ready](https://img.shields.io/badge/production-ready-green)
4
+
5
+
6
+ **Rule Engine, Inference, and Pattern Matching** *(Optional Extension)*
7
+
8
+ Apply business rules and inference to RDF data. Includes reasoning engine and pattern matching.
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ pnpm add @unrdf/knowledge-engine
14
+ ```
15
+
16
+ ## 📚 Examples
17
+
18
+ See these examples that demonstrate @unrdf/knowledge-engine:
19
+
20
+ - **[knowledge-engine-example.mjs](../../examples/knowledge-engine-example.mjs)** - Complete AI semantic analysis demo (1 hour)
21
+ - **[ai-semantic-example.mjs](../../examples/ai-semantic-example.mjs)** - Embedding-based semantic search
22
+ - **[comprehensive-feature-test.mjs](../../examples/comprehensive-feature-test.mjs)** - Knowledge engine integration
23
+
24
+ **Want AI-powered queries?** Start with [knowledge-engine-example.mjs](../../examples/knowledge-engine-example.mjs).
25
+
26
+ ## Quick Start
27
+
28
+ ```javascript
29
+ import { inferPatterns, createRuleSet } from '@unrdf/knowledge-engine'
30
+
31
+ // Define rules
32
+ const rules = createRuleSet([
33
+ {
34
+ name: 'infer-person',
35
+ pattern: '?x rdf:type foaf:Person',
36
+ then: '?x rdfs:label ?name'
37
+ }
38
+ ])
39
+
40
+ // Apply inference
41
+ const inferred = await inferPatterns(store, rules)
42
+ ```
43
+
44
+ ## Features
45
+
46
+ - ✅ Forward chaining inference
47
+ - ✅ Rule definition and execution
48
+ - ✅ Pattern matching on RDF data
49
+ - ✅ Built-in ontology reasoning (RDF, RDFS, OWL)
50
+ - ✅ Custom rule sets
51
+ - ✅ Performance optimization
52
+
53
+ ## Use Cases
54
+
55
+ - **Business rules**: Apply domain rules to RDF
56
+ - **Data enrichment**: Infer new facts from existing data
57
+ - **Ontology reasoning**: RDFS and OWL inference
58
+ - **Data quality**: Detect and fix inconsistencies
59
+ - **Knowledge extraction**: Mine patterns from data
60
+
61
+ ## Documentation
62
+
63
+ - **[API Reference](./docs/API.md)** - Complete API documentation
64
+ - **[User Guide](./docs/GUIDE.md)** - Rule definition and usage
65
+ - **[Examples](./examples/)** - Code examples
66
+ - **[Contributing](./docs/CONTRIBUTING.md)** - How to contribute
67
+
68
+ ## Status
69
+
70
+ **Optional Extension** - Not required for core UNRDF functionality.
71
+ Use only if you need rule-based inference.
72
+
73
+ ## Depends On
74
+
75
+ - `@unrdf/core` - RDF substrate
76
+ - `@unrdf/streaming` - Change subscriptions
77
+
78
+ ## VOC Usage
79
+
80
+ - VOC-3: ML Agent (pattern matching)
81
+
82
+ ## License
83
+
84
+ MIT
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@unrdf/knowledge-engine",
3
+ "version": "5.0.1",
4
+ "description": "UNRDF Knowledge Engine - Rule Engine, Inference, and Pattern Matching (Optional Extension)",
5
+ "type": "module",
6
+ "main": "src/index.mjs",
7
+ "exports": {
8
+ ".": "./src/index.mjs",
9
+ "./query": "./src/query.mjs",
10
+ "./canonicalize": "./src/canonicalize.mjs",
11
+ "./parse": "./src/parse.mjs"
12
+ },
13
+ "sideEffects": false,
14
+ "files": [
15
+ "src/",
16
+ "dist/",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "keywords": [
21
+ "rdf",
22
+ "knowledge-engine",
23
+ "inference",
24
+ "reasoning",
25
+ "rules"
26
+ ],
27
+ "dependencies": {
28
+ "eyereasoner": "^18.23.0",
29
+ "@unrdf/core": "5.0.1",
30
+ "@unrdf/streaming": "5.0.1"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^24.10.1",
34
+ "vitest": "^4.0.15"
35
+ },
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/unrdf/unrdf.git",
42
+ "directory": "packages/knowledge-engine"
43
+ },
44
+ "bugs": {
45
+ "url": "https://github.com/unrdf/unrdf/issues"
46
+ },
47
+ "homepage": "https://github.com/unrdf/unrdf#readme",
48
+ "license": "MIT",
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "scripts": {
53
+ "test": "vitest run --coverage",
54
+ "test:fast": "vitest run --coverage",
55
+ "test:watch": "vitest --coverage",
56
+ "build": "node build.config.mjs",
57
+ "lint": "eslint src/ test/ --max-warnings=0",
58
+ "lint:fix": "eslint src/ test/ --fix",
59
+ "format": "prettier --write src/ test/",
60
+ "format:check": "prettier --check src/ test/",
61
+ "clean": "rm -rf dist/ .nyc_output/ coverage/",
62
+ "dev": "echo 'Development mode for @unrdf/knowledge-engine'"
63
+ }
64
+ }
@@ -0,0 +1,343 @@
1
+ /**
2
+ * @file Browser compatibility shims for Node.js APIs
3
+ * @module browser-shims
4
+ *
5
+ * @description
6
+ * Provides browser-compatible polyfills for Node.js APIs used in the knowledge engine.
7
+ * This allows the same codebase to work in both Node.js and browser environments.
8
+ */
9
+
10
+ /**
11
+ * Check if we're running in a browser environment
12
+ */
13
+ export const isBrowser =
14
+ typeof globalThis?.window !== 'undefined' && typeof globalThis?.window?.document !== 'undefined';
15
+
16
+ /**
17
+ * Check if we're running in Node.js environment
18
+ */
19
+ export const isNode = (() => {
20
+ try {
21
+ return typeof process !== 'undefined' && !!process?.versions?.node;
22
+ } catch {
23
+ return false;
24
+ }
25
+ })();
26
+
27
+ // Random UUID generation - use crypto.randomUUID if available, otherwise fallback
28
+ /**
29
+ *
30
+ */
31
+ export function randomUUID() {
32
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
33
+ return crypto.randomUUID();
34
+ }
35
+
36
+ // Fallback UUID generation
37
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
38
+ const r = (Math.random() * 16) | 0;
39
+ const v = c === 'x' ? r : (r & 0x3) | 0x8;
40
+ return v.toString(16);
41
+ });
42
+ }
43
+
44
+ // Path utilities - browser-compatible version
45
+ export const path = {
46
+ join: (...args) => args.filter(Boolean).join('/').replace(/\/+/g, '/'),
47
+ resolve: (...args) => args.filter(Boolean).join('/').replace(/\/+/g, '/'),
48
+ dirname: path => path.replace(/\/$/, '').split('/').slice(0, -1).join('/') || '.',
49
+ basename: path => path.split('/').pop() || '',
50
+ extname: path => {
51
+ const ext = path.split('.').pop();
52
+ return ext && ext !== path ? '.' + ext : '';
53
+ },
54
+ };
55
+
56
+ // Process utilities
57
+ export const process = {
58
+ cwd: () => '/',
59
+ env: isBrowser
60
+ ? {}
61
+ : (() => {
62
+ try {
63
+ return process.env;
64
+ } catch {
65
+ return {};
66
+ }
67
+ })(),
68
+ versions: isBrowser
69
+ ? {}
70
+ : (() => {
71
+ try {
72
+ return process.versions;
73
+ } catch {
74
+ return {};
75
+ }
76
+ })(),
77
+ };
78
+
79
+ // File system operations - browser-compatible (no-ops or memory-based)
80
+ class BrowserFileSystem {
81
+ #files = new Map();
82
+ #directories = new Set(['/']);
83
+
84
+ constructor() {
85
+ // Create some default directories
86
+ this.#directories.add('/src');
87
+ this.#directories.add('/dist');
88
+ this.#directories.add('/examples');
89
+ }
90
+
91
+ clear() {
92
+ this.#files.clear();
93
+ this.#directories.clear();
94
+ this.#directories.add('/');
95
+ this.#directories.add('/src');
96
+ this.#directories.add('/dist');
97
+ this.#directories.add('/examples');
98
+ }
99
+
100
+ existsSync(path) {
101
+ return this.#files.has(path) || this.#directories.has(path);
102
+ }
103
+
104
+ readFileSync(path, encoding = 'utf8') {
105
+ const content = this.#files.get(path);
106
+ if (!content) {
107
+ throw new Error(`ENOENT: no such file or directory, open '${path}'`);
108
+ }
109
+ return encoding === 'utf8' ? content : Buffer.from(content, 'utf8');
110
+ }
111
+
112
+ writeFileSync(path, data, encoding = 'utf8') {
113
+ const content = encoding === 'utf8' ? data : data.toString();
114
+ this.#files.set(path, content);
115
+
116
+ // Ensure parent directories exist
117
+ const parent = path.dirname(path);
118
+ if (!this.#directories.has(parent) && parent !== path) {
119
+ this.#directories.add(parent);
120
+ }
121
+ }
122
+
123
+ mkdirSync(path, _options = {}) {
124
+ if (this.#directories.has(path)) {
125
+ throw new Error(`EEXIST: file already exists, mkdir '${path}'`);
126
+ }
127
+ this.#directories.add(path);
128
+ }
129
+
130
+ readdirSync(path) {
131
+ return Array.from(this.#files.keys()).filter(file => file.startsWith(path + '/'));
132
+ }
133
+
134
+ // Async versions
135
+ async readFile(path, encoding = 'utf8') {
136
+ return Promise.resolve(this.readFileSync(path, encoding));
137
+ }
138
+
139
+ async writeFile(path, data, encoding = 'utf8') {
140
+ this.writeFileSync(path, data, encoding);
141
+ return Promise.resolve();
142
+ }
143
+
144
+ async mkdir(path, options = {}) {
145
+ this.mkdirSync(path, options);
146
+ return Promise.resolve();
147
+ }
148
+ }
149
+
150
+ export const fs = isBrowser
151
+ ? new BrowserFileSystem()
152
+ : await import('node:fs').then(m => m.default);
153
+ export const fsPromises = isBrowser
154
+ ? new BrowserFileSystem()
155
+ : await import('node:fs/promises').then(m => m.default);
156
+
157
+ // Worker thread polyfill for browser
158
+ /**
159
+ *
160
+ */
161
+ export class BrowserWorker {
162
+ /**
163
+ *
164
+ */
165
+ constructor(source, options = {}) {
166
+ if (typeof source === 'string' && isBrowser) {
167
+ // Convert string to blob URL (browser only)
168
+ const blob = new Blob([source], { type: 'application/javascript' });
169
+ this.worker = new Worker(URL.createObjectURL(blob), options);
170
+ } else if (typeof source === 'string' && isNode) {
171
+ // In Node.js, can't create Worker from inline code - need a file
172
+ // Create a mock worker for testing purposes
173
+ this.worker = null;
174
+ this.mockMode = true;
175
+ } else {
176
+ // Assume it's a file path
177
+ this.worker = new Worker(source, options);
178
+ }
179
+
180
+ this.messageHandlers = [];
181
+ this.errorHandlers = [];
182
+ this.exitHandlers = [];
183
+ this.terminated = false;
184
+
185
+ if (this.worker) {
186
+ this.worker.onmessage = event => {
187
+ this.messageHandlers.forEach(handler => handler(event.data));
188
+ };
189
+
190
+ this.worker.onerror = error => {
191
+ this.errorHandlers.forEach(handler => handler(error));
192
+ };
193
+ }
194
+ }
195
+
196
+ /**
197
+ *
198
+ */
199
+ postMessage(data) {
200
+ if (this.terminated) return;
201
+ if (this.worker) {
202
+ this.worker.postMessage(data);
203
+ }
204
+ }
205
+
206
+ /**
207
+ *
208
+ */
209
+ terminate() {
210
+ this.terminated = true;
211
+ if (this.worker) {
212
+ this.worker.terminate();
213
+ }
214
+ }
215
+
216
+ /**
217
+ *
218
+ */
219
+ on(event, handler) {
220
+ switch (event) {
221
+ case 'message':
222
+ this.messageHandlers.push(handler);
223
+ break;
224
+ case 'error':
225
+ this.errorHandlers.push(handler);
226
+ break;
227
+ case 'exit':
228
+ this.exitHandlers.push(handler);
229
+ break;
230
+ }
231
+ }
232
+
233
+ /**
234
+ *
235
+ */
236
+ once(event, handler) {
237
+ const wrappedHandler = data => {
238
+ handler(data);
239
+ this.removeListener(event, wrappedHandler);
240
+ };
241
+ this.on(event, wrappedHandler);
242
+ }
243
+
244
+ /**
245
+ *
246
+ */
247
+ removeListener(event, handler) {
248
+ switch (event) {
249
+ case 'message':
250
+ this.messageHandlers = this.messageHandlers.filter(h => h !== handler);
251
+ break;
252
+ case 'error':
253
+ this.errorHandlers = this.errorHandlers.filter(h => h !== handler);
254
+ break;
255
+ case 'exit':
256
+ this.exitHandlers = this.exitHandlers.filter(h => h !== handler);
257
+ break;
258
+ }
259
+ }
260
+ }
261
+
262
+ export const Worker = isBrowser
263
+ ? BrowserWorker
264
+ : await import('node:worker_threads').then(m => m.Worker);
265
+
266
+ // Mock child_process.execSync - browser-compatible
267
+ /**
268
+ *
269
+ */
270
+ export async function execSync(command, options = {}) {
271
+ if (isBrowser) {
272
+ console.warn(`[Browser] execSync not available in browser: ${command}`);
273
+ return ''; // Return empty string as mock
274
+ }
275
+
276
+ const { execSync: nodeExecSync } = await import('child_process');
277
+ const result = nodeExecSync(command, { encoding: 'utf8', ...options });
278
+ // Ensure we return a string, not a Buffer
279
+ return typeof result === 'string' ? result : result.toString('utf8');
280
+ }
281
+
282
+ // Hash utilities - use Web Crypto API in browser
283
+ /**
284
+ *
285
+ */
286
+ export class BrowserHash {
287
+ /**
288
+ *
289
+ */
290
+ constructor(algorithm = 'SHA-256') {
291
+ this.algorithm = algorithm.toLowerCase().replace(/[^a-z0-9]/g, '');
292
+ }
293
+
294
+ /**
295
+ *
296
+ */
297
+ update(data) {
298
+ this.data = typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data);
299
+ return this;
300
+ }
301
+
302
+ /**
303
+ *
304
+ */
305
+ async digest(encoding = 'hex') {
306
+ const hashBuffer = await crypto.subtle.digest(this.algorithm, this.data);
307
+ const hashArray = new Uint8Array(hashBuffer);
308
+
309
+ if (encoding === 'hex') {
310
+ return Array.from(hashArray)
311
+ .map(b => b.toString(16).padStart(2, '0'))
312
+ .join('');
313
+ }
314
+
315
+ return hashArray;
316
+ }
317
+ }
318
+
319
+ /**
320
+ *
321
+ */
322
+ export async function createHash(algorithm) {
323
+ if (isBrowser) {
324
+ return new BrowserHash(algorithm);
325
+ }
326
+
327
+ const { createHash: nodeCreateHash } = await import('node:crypto');
328
+ return nodeCreateHash(algorithm);
329
+ }
330
+
331
+ // Export all shims as a unified object
332
+ export default {
333
+ isBrowser,
334
+ isNode,
335
+ randomUUID,
336
+ path,
337
+ process,
338
+ fs,
339
+ fsPromises,
340
+ Worker: BrowserWorker,
341
+ execSync,
342
+ createHash,
343
+ };