@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
package/src/query.mjs DELETED
@@ -1,306 +0,0 @@
1
- /**
2
- * @file SPARQL querying utilities.
3
- * @module query
4
- */
5
-
6
- import { createStore } from '@unrdf/oxigraph';
7
- import { trace, SpanStatusCode } from '@opentelemetry/api';
8
-
9
- const tracer = trace.getTracer('unrdf');
10
-
11
- /**
12
- * Run a SPARQL query against a store.
13
- * @param {Store} store - The n3.Store to query against
14
- * @param {string} sparql - The SPARQL query string
15
- * @param {Object} [options] - Query options (for compatibility)
16
- * @param {number} [options.limit] - Maximum number of results
17
- * @returns {Promise<any>} Promise resolving to the query result
18
- *
19
- * @throws {Error} If query execution fails
20
- *
21
- * @example
22
- * const store = new Store();
23
- * // ... add quads to store
24
- *
25
- * const results = await query(store, `
26
- * SELECT ?s ?o WHERE {
27
- * ?s <http://example.org/knows> ?o
28
- * }
29
- * `);
30
- * console.log(results); // Array of binding objects
31
- */
32
- export async function query(store, sparql, _options = {}) {
33
- if (!store || typeof store.getQuads !== 'function') {
34
- throw new TypeError('query: store must be a valid Store instance');
35
- }
36
- if (typeof sparql !== 'string' || !sparql.trim()) {
37
- throw new TypeError('query: sparql must be a non-empty string');
38
- }
39
-
40
- return tracer.startActiveSpan('query.sparql', async span => {
41
- const startTime = performance.now();
42
- try {
43
- const queryType = sparql.trim().split(/\s+/)[0].toUpperCase();
44
- span.setAttributes({
45
- 'query.type': queryType,
46
- 'query.length': sparql.length,
47
- 'query.store_size': store.size,
48
- });
49
-
50
- // Convert n3.Store quads to substrate store (synchronous)
51
- const quads = store.getQuads();
52
- const rdfStore = createStore(Array.from(quads));
53
-
54
- // Execute query synchronously
55
- let result;
56
- try {
57
- const queryResult = rdfStore.query(sparql);
58
-
59
- // Determine result type and format accordingly
60
- if (Array.isArray(queryResult)) {
61
- // SELECT query result (array of bindings)
62
- if (
63
- queryResult.length > 0 &&
64
- typeof queryResult[0] === 'object' &&
65
- !queryResult[0].subject
66
- ) {
67
- // Already formatted bindings
68
- result = queryResult;
69
- } else {
70
- // Check query type to determine formatting
71
- if (queryType === 'CONSTRUCT' || queryType === 'DESCRIBE') {
72
- // Return Oxigraph store directly with quads
73
- result = rdfStore;
74
- span.setAttribute('query.result_count', result.size);
75
- } else {
76
- // SELECT - format as bindings array
77
- result = queryResult.map(item => {
78
- if (item instanceof Map) {
79
- // Handle Map objects from Oxigraph
80
- const bindings = {};
81
- for (const [key, val] of item.entries()) {
82
- bindings[key] =
83
- val && val.value ? val.value : val && val.toString ? val.toString() : val;
84
- }
85
- return bindings;
86
- } else if (item && typeof item === 'object') {
87
- return Object.fromEntries(
88
- Object.entries(item).map(([k, v]) => [k, v && v.value ? v.value : v])
89
- );
90
- }
91
- return item;
92
- });
93
- span.setAttribute('query.result_count', result.length);
94
- }
95
- }
96
- } else if (typeof queryResult === 'boolean') {
97
- // ASK query
98
- result = queryResult;
99
- span.setAttribute('query.result_type', 'boolean');
100
- span.setAttribute('query.result', result);
101
- } else {
102
- // CONSTRUCT/DESCRIBE - return rdfStore directly (it's already an Oxigraph store)
103
- result = rdfStore;
104
- span.setAttribute('query.result_count', result.size);
105
- }
106
- } catch (engineError) {
107
- // If query execution fails, provide helpful error
108
- throw new Error(`Query execution failed: ${engineError.message}`);
109
- }
110
-
111
- span.setStatus({ code: SpanStatusCode.OK });
112
- const duration = performance.now() - startTime;
113
- span.setAttribute('query.duration_ms', duration);
114
- return result;
115
- } catch (error) {
116
- span.recordException(error);
117
- span.setStatus({
118
- code: SpanStatusCode.ERROR,
119
- message: error.message,
120
- });
121
- throw new Error(`SPARQL query failed: ${error.message}`);
122
- } finally {
123
- span.end();
124
- }
125
- });
126
- }
127
-
128
- /**
129
- * Execute a SELECT query and return bindings.
130
- * @param {Store} store - The store to query against
131
- * @param {string} sparql - The SPARQL SELECT query
132
- * @param {Object} [options] - Query options
133
- * @returns {Promise<Array<Object>>} Promise resolving to array of binding objects
134
- *
135
- * @throws {Error} If query execution fails
136
- *
137
- * @example
138
- * const bindings = await select(store, `
139
- * SELECT ?name ?age WHERE {
140
- * ?person <http://example.org/name> ?name ;
141
- * <http://example.org/age> ?age .
142
- * }
143
- * `);
144
- */
145
- export async function select(store, sparql, options = {}) {
146
- const result = await query(store, sparql, options);
147
- if (Array.isArray(result)) {
148
- return result;
149
- }
150
- throw new Error('SELECT query did not return bindings');
151
- }
152
-
153
- /**
154
- * Execute an ASK query and return boolean result.
155
- * @param {Store} store - The store to query against
156
- * @param {string} sparql - The SPARQL ASK query
157
- * @param {Object} [options] - Query options
158
- * @returns {Promise<boolean>} Promise resolving to boolean result
159
- *
160
- * @throws {Error} If query execution fails
161
- *
162
- * @example
163
- * const hasData = await ask(store, `
164
- * ASK WHERE {
165
- * ?s ?p ?o .
166
- * }
167
- * `);
168
- */
169
- export async function ask(store, sparql, options = {}) {
170
- const result = await query(store, sparql, options);
171
- if (typeof result === 'boolean') {
172
- return result;
173
- }
174
- throw new Error('ASK query did not return boolean result');
175
- }
176
-
177
- /**
178
- * Execute a CONSTRUCT query and return a new store.
179
- * @param {Store} store - The store to query against
180
- * @param {string} sparql - The SPARQL CONSTRUCT query
181
- * @param {Object} [options] - Query options
182
- * @returns {Promise<Store>} Promise resolving to a new store with constructed quads
183
- *
184
- * @throws {Error} If query execution fails
185
- *
186
- * @example
187
- * const constructed = await construct(store, `
188
- * CONSTRUCT {
189
- * ?person <http://example.org/type> <http://example.org/Person> .
190
- * } WHERE {
191
- * ?person <http://example.org/name> ?name .
192
- * }
193
- * `);
194
- */
195
- export async function construct(store, sparql, options = {}) {
196
- const result = await query(store, sparql, options);
197
- if (result && typeof result.getQuads === 'function') {
198
- return result;
199
- }
200
- throw new Error('CONSTRUCT query did not return a store');
201
- }
202
-
203
- /**
204
- * Execute a DESCRIBE query and return a new store.
205
- * @param {Store} store - The store to query against
206
- * @param {string} sparql - The SPARQL DESCRIBE query
207
- * @param {Object} [options] - Query options
208
- * @returns {Promise<Store>} Promise resolving to a new store with described quads
209
- *
210
- * @throws {Error} If query execution fails
211
- *
212
- * @example
213
- * const described = await describe(store, `
214
- * DESCRIBE <http://example.org/alice>
215
- * `);
216
- */
217
- export async function describe(store, sparql, options = {}) {
218
- const result = await query(store, sparql, options);
219
- if (result && typeof result.getQuads === 'function') {
220
- return result;
221
- }
222
- throw new Error('DESCRIBE query did not return a store');
223
- }
224
-
225
- /**
226
- * Execute a SPARQL UPDATE operation (INSERT, DELETE, etc.).
227
- * @param {Store} store - The store to update
228
- * @param {string} sparql - The SPARQL UPDATE query
229
- * @param {Object} [options] - Update options
230
- * @returns {Promise<Store>} Promise resolving to the updated store
231
- *
232
- * @throws {Error} If update execution fails
233
- *
234
- * @example
235
- * const updated = await update(store, `
236
- * INSERT DATA {
237
- * <http://example.org/alice> <http://example.org/age> "30" .
238
- * }
239
- * `);
240
- */
241
- export async function update(store, sparql, _options = {}) {
242
- if (!store || typeof store.getQuads !== 'function') {
243
- throw new TypeError('update: store must be a valid Store instance');
244
- }
245
- if (typeof sparql !== 'string' || !sparql.trim()) {
246
- throw new TypeError('update: sparql must be a non-empty string');
247
- }
248
-
249
- try {
250
- // Convert n3.Store to substrate store for update
251
- const quads = store.getQuads();
252
- const rdfStore = createStore(Array.from(quads));
253
-
254
- // Execute update synchronously
255
- rdfStore.query(sparql);
256
-
257
- // Return the updated store
258
- return store;
259
- } catch (error) {
260
- throw new Error(`SPARQL update failed: ${error.message}`);
261
- }
262
- }
263
-
264
- /**
265
- * Get query execution statistics.
266
- * @param {Store} store - The store to query against
267
- * @param {string} sparql - The SPARQL query
268
- * @param {Object} [options] - Query options
269
- * @returns {Promise<Object>} Promise resolving to execution statistics
270
- *
271
- * @example
272
- * const stats = await getQueryStats(store, sparql);
273
- * console.log(`Execution time: ${stats.duration}ms`);
274
- * console.log(`Result count: ${stats.resultCount}`);
275
- */
276
- export async function getQueryStats(store, sparql, options = {}) {
277
- const startTime = Date.now();
278
-
279
- try {
280
- const result = await query(store, sparql, options);
281
- const endTime = Date.now();
282
-
283
- let resultCount = 0;
284
- if (Array.isArray(result)) {
285
- resultCount = result.length;
286
- } else if (result && typeof result.getQuads === 'function') {
287
- resultCount = result.size;
288
- } else if (typeof result === 'boolean') {
289
- resultCount = 1;
290
- }
291
-
292
- return {
293
- duration: endTime - startTime,
294
- resultCount,
295
- success: true,
296
- };
297
- } catch (error) {
298
- const endTime = Date.now();
299
- return {
300
- duration: endTime - startTime,
301
- resultCount: 0,
302
- success: false,
303
- error: error.message,
304
- };
305
- }
306
- }
package/src/reason.mjs DELETED
@@ -1,350 +0,0 @@
1
- /**
2
- * @file Reasoning support using N3 rules.
3
- * @module reason
4
- */
5
-
6
- import { Parser, Writer } from '@unrdf/core/rdf/n3-justified-only';
7
- import { createStore } from '@unrdf/oxigraph'; // TODO: Replace with Oxigraph Store
8
-
9
- // Dynamic import to avoid top-level await issues
10
- let basicQuery;
11
- const loadBasicQuery = async () => {
12
- if (!basicQuery) {
13
- const eyereasoner = await import('eyereasoner');
14
- basicQuery = eyereasoner.basicQuery;
15
- }
16
- return basicQuery;
17
- };
18
-
19
- /**
20
- * Run forward-chaining reasoning with N3 rules.
21
- * @param {Store} store - The store containing data to reason over
22
- * @param {Store|string} rules - The store or Turtle string containing N3 rules
23
- * @param {Object} [options] - Reasoning options
24
- * @param {boolean} [options.includeOriginal] - Include original data in result
25
- * @param {number} [options.maxIterations] - Maximum number of reasoning iterations
26
- * @param {boolean} [options.debug] - Enable debug output
27
- * @returns {Promise<Store>} Promise resolving to a new store containing original and inferred quads
28
- *
29
- * @throws {Error} If reasoning fails
30
- *
31
- * @example
32
- * const dataStore = createStore();
33
- * // ... add data quads to store
34
- *
35
- * const rulesTtl = `
36
- * @prefix ex: <http://example.org/> .
37
- * @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
38
- *
39
- * { ?x ex:parent ?y } => { ?x rdfs:subClassOf ?y } .
40
- * `;
41
- *
42
- * const reasonedStore = await reason(dataStore, rulesTtl);
43
- * console.log('Original quads:', dataStore.size);
44
- * console.log('Reasoned quads:', reasonedStore.size);
45
- */
46
- export async function reason(store, rules, options = {}) {
47
- if (!store || typeof store.getQuads !== 'function') {
48
- throw new TypeError('reason: store must be a valid Store instance');
49
- }
50
- if (!rules) {
51
- throw new TypeError('reason: rules must be provided');
52
- }
53
-
54
- const { includeOriginal = true, _maxIterations = 100, debug = false } = options;
55
-
56
- try {
57
- // Get data quads from store
58
- const dataQuads = store.getQuads();
59
-
60
- // Convert rules to quads if needed
61
- let rulesQuads;
62
- if (typeof rules === 'string') {
63
- // Parse Turtle rules to quads
64
- const parser = new Parser();
65
- rulesQuads = parser.parse(rules);
66
- } else if (rules && typeof rules.getQuads === 'function') {
67
- rulesQuads = rules.getQuads();
68
- } else {
69
- throw new TypeError('reason: rules must be a Store or Turtle string');
70
- }
71
-
72
- if (debug) {
73
- console.log('Data quads:', dataQuads.length);
74
- console.log('Rules quads:', rulesQuads.length);
75
- }
76
-
77
- // Run reasoning using EYE reasoner
78
- // Load basicQuery dynamically to avoid top-level await issues
79
- const query = await loadBasicQuery();
80
-
81
- // Combine data and rules as EYE expects
82
- const combinedQuads = [...dataQuads, ...rulesQuads];
83
- const { result } = await query(combinedQuads, []);
84
-
85
- if (debug) {
86
- console.log('Result quads:', result.length);
87
- }
88
-
89
- // Create result store
90
- const _resultStore = createStore(result);
91
-
92
- // Combine original and inferred data if requested
93
- if (includeOriginal) {
94
- return createStore([...dataQuads, ...result]);
95
- } else {
96
- // Extract only inferred quads (not in original data)
97
- const originalQuadSet = new Set(dataQuads.map(q => q.toString()));
98
- const inferredQuads = result.filter(q => !originalQuadSet.has(q.toString()));
99
- return createStore(inferredQuads);
100
- }
101
- } catch (error) {
102
- throw new Error(`N3 reasoning failed: ${error.message}`);
103
- }
104
- }
105
-
106
- /**
107
- * Run reasoning with multiple rule sets.
108
- * @param {Store} store - The store containing data to reason over
109
- * @param {Array<Store|string>} rulesList - Array of stores or Turtle strings containing N3 rules
110
- * @param {Object} [options] - Reasoning options
111
- * @returns {Promise<Store>} Promise resolving to a new store with all reasoning results
112
- *
113
- * @throws {Error} If reasoning fails
114
- *
115
- * @example
116
- * const rulesList = [
117
- * rdfsRulesTtl,
118
- * owlRulesTtl,
119
- * customRulesTtl
120
- * ];
121
- *
122
- * const reasonedStore = await reasonMultiple(store, rulesList);
123
- */
124
- export async function reasonMultiple(store, rulesList, options = {}) {
125
- if (!store || typeof store.getQuads !== 'function') {
126
- throw new TypeError('reasonMultiple: store must be a valid Store instance');
127
- }
128
- if (!Array.isArray(rulesList) || rulesList.length === 0) {
129
- throw new TypeError('reasonMultiple: rulesList must be a non-empty array');
130
- }
131
-
132
- try {
133
- let currentStore = store;
134
-
135
- for (let i = 0; i < rulesList.length; i++) {
136
- const rules = rulesList[i];
137
- if (options.debug) {
138
- console.log(`Applying rule set ${i + 1}/${rulesList.length}`);
139
- }
140
-
141
- currentStore = await reason(currentStore, rules, {
142
- ...options,
143
- includeOriginal: true, // Always include original data for subsequent rule applications
144
- });
145
- }
146
-
147
- return currentStore;
148
- } catch (error) {
149
- throw new Error(`Multiple N3 reasoning failed: ${error.message}`);
150
- }
151
- }
152
-
153
- /**
154
- * Extract only the newly inferred quads from reasoning.
155
- * @param {Store} originalStore - The original store before reasoning
156
- * @param {Store} reasonedStore - The store after reasoning
157
- * @returns {Store} Store containing only the newly inferred quads
158
- *
159
- * @example
160
- * const originalStore = createStore();
161
- * // ... add original quads
162
- *
163
- * const reasonedStore = await reason(originalStore, rules);
164
- * const inferredOnly = extractInferred(originalStore, reasonedStore);
165
- * console.log('Newly inferred quads:', inferredOnly.size);
166
- */
167
- export function extractInferred(originalStore, reasonedStore) {
168
- if (!originalStore || typeof originalStore.getQuads !== 'function') {
169
- throw new TypeError('extractInferred: originalStore must be a valid Store instance');
170
- }
171
- if (!reasonedStore || typeof reasonedStore.getQuads !== 'function') {
172
- throw new TypeError('extractInferred: reasonedStore must be a valid Store instance');
173
- }
174
-
175
- const originalQuads = new Set(originalStore.getQuads().map(q => q.toString()));
176
- const reasonedQuads = reasonedStore.getQuads();
177
-
178
- const inferredQuads = reasonedQuads.filter(q => !originalQuads.has(q.toString()));
179
-
180
- return createStore(inferredQuads);
181
- }
182
-
183
- /**
184
- * Get reasoning statistics.
185
- * @param {Store} originalStore - The original store before reasoning
186
- * @param {Store} reasonedStore - The store after reasoning
187
- * @returns {Object} Reasoning statistics
188
- *
189
- * @example
190
- * const stats = getReasoningStats(originalStore, reasonedStore);
191
- * console.log(`Original quads: ${stats.originalCount}`);
192
- * console.log(`Inferred quads: ${stats.inferredCount}`);
193
- * console.log(`Total quads: ${stats.totalCount}`);
194
- * console.log(`Inference ratio: ${stats.inferenceRatio}`);
195
- */
196
- export function getReasoningStats(originalStore, reasonedStore) {
197
- if (!originalStore || typeof originalStore.getQuads !== 'function') {
198
- throw new TypeError('getReasoningStats: originalStore must be a valid Store instance');
199
- }
200
- if (!reasonedStore || typeof reasonedStore.getQuads !== 'function') {
201
- throw new TypeError('getReasoningStats: reasonedStore must be a valid Store instance');
202
- }
203
-
204
- const originalCount = originalStore.size;
205
- const totalCount = reasonedStore.size;
206
- const inferredCount = totalCount - originalCount;
207
- const inferenceRatio = originalCount > 0 ? inferredCount / originalCount : 0;
208
-
209
- return {
210
- originalCount,
211
- inferredCount,
212
- totalCount,
213
- inferenceRatio,
214
- hasInferences: inferredCount > 0,
215
- };
216
- }
217
-
218
- /**
219
- * Validate N3 rules syntax.
220
- * @param {Store|string} rules - The store or Turtle string containing N3 rules
221
- * @returns {Object} Validation result
222
- *
223
- * @example
224
- * const validation = validateRules(rulesTtl);
225
- * if (!validation.valid) {
226
- * console.log('Rule validation errors:', validation.errors);
227
- * }
228
- */
229
- export function validateRules(rules) {
230
- if (!rules) {
231
- return { valid: false, errors: ['Rules must be provided'] };
232
- }
233
-
234
- try {
235
- let rulesTurtle;
236
- if (typeof rules === 'string') {
237
- rulesTurtle = rules;
238
- } else if (rules && typeof rules.getQuads === 'function') {
239
- const writer = new Writer({ format: 'Turtle' });
240
- writer.addQuads(rules.getQuads());
241
- rulesTurtle = writer.quadsToString(rules.getQuads());
242
- } else {
243
- return {
244
- valid: false,
245
- errors: ['Rules must be a Store or Turtle string'],
246
- };
247
- }
248
-
249
- // Basic syntax validation
250
- const parser = new Parser();
251
- parser.parse(rulesTurtle);
252
-
253
- return { valid: true, errors: [] };
254
- } catch (error) {
255
- return { valid: false, errors: [error.message] };
256
- }
257
- }
258
-
259
- /**
260
- * Create a reasoning session with persistent state.
261
- * @param {Store} initialStore - Initial store state
262
- * @param {Store|string} rules - N3 rules to apply
263
- * @param {Object} [options] - Session options
264
- * @returns {Object} Reasoning session object
265
- *
266
- * @example
267
- * const session = createReasoningSession(store, rules);
268
- *
269
- * // Add new data
270
- * session.addData(newQuads);
271
- *
272
- * // Apply reasoning
273
- * await session.reason();
274
- *
275
- * // Get current state
276
- * const currentState = session.getState();
277
- */
278
- export function createReasoningSession(initialStore, rules, options = {}) {
279
- if (!initialStore || typeof initialStore.getQuads !== 'function') {
280
- throw new TypeError('createReasoningSession: initialStore must be a valid Store instance');
281
- }
282
- if (!rules) {
283
- throw new TypeError('createReasoningSession: rules must be provided');
284
- }
285
-
286
- let currentStore = createStore(initialStore.getQuads());
287
- const sessionRules = rules;
288
-
289
- return {
290
- /**
291
- * Add new data to the session.
292
- * @param {Array|Quad} quads - Quads to add
293
- */
294
- addData(quads) {
295
- if (Array.isArray(quads)) {
296
- currentStore.addQuads(quads);
297
- } else {
298
- currentStore.add(quads);
299
- }
300
- },
301
-
302
- /**
303
- * Remove data from the session.
304
- * @param {Array|Quad} quads - Quads to remove
305
- */
306
- removeData(quads) {
307
- if (Array.isArray(quads)) {
308
- currentStore.removeQuads(quads);
309
- } else {
310
- currentStore.delete(quads);
311
- }
312
- },
313
-
314
- /**
315
- * Apply reasoning to current state.
316
- * @param {Object} [reasonOptions] - Reasoning options
317
- * @returns {Promise<Store>} Updated store
318
- */
319
- async reason(reasonOptions = {}) {
320
- currentStore = await reason(currentStore, sessionRules, {
321
- ...options,
322
- ...reasonOptions,
323
- });
324
- return currentStore;
325
- },
326
-
327
- /**
328
- * Get current store state.
329
- * @returns {Store} Current store
330
- */
331
- getState() {
332
- return createStore(currentStore.getQuads());
333
- },
334
-
335
- /**
336
- * Reset to initial state.
337
- */
338
- reset() {
339
- currentStore = createStore(initialStore.getQuads());
340
- },
341
-
342
- /**
343
- * Get session statistics.
344
- * @returns {Object} Session statistics
345
- */
346
- getStats() {
347
- return getReasoningStats(initialStore, currentStore);
348
- },
349
- };
350
- }