@unrdf/knowledge-engine 5.0.1 → 26.4.2
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.
- package/package.json +23 -17
- package/src/ai-enhanced-search.mjs +371 -0
- package/src/anomaly-detector.mjs +226 -0
- package/src/artifact-generator.mjs +252 -0
- package/src/browser.mjs +1 -1
- package/src/chatman/disruption-arithmetic.mjs +140 -0
- package/src/chatman/market-dynamics.mjs +140 -0
- package/src/chatman/organizational-dynamics.mjs +140 -0
- package/src/chatman/strategic-dynamics.mjs +140 -0
- package/src/chatman-config-loader.mjs +282 -0
- package/src/chatman-engine.mjs +435 -0
- package/src/chatman-operator.mjs +343 -0
- package/src/dark-field-detector.mjs +332 -0
- package/src/formation-theorems.mjs +345 -0
- package/src/index.mjs +20 -2
- package/src/knowledge-hook-manager.mjs +1 -1
- package/src/lockchain-writer-browser.mjs +2 -2
- package/src/observability.mjs +40 -4
- package/src/query-optimizer.mjs +1 -1
- package/src/resolution-layer.mjs +1 -1
- package/src/transaction.mjs +11 -9
- package/README.md +0 -84
- package/src/browser-shims.mjs +0 -343
- package/src/canonicalize.mjs +0 -414
- package/src/condition-cache.mjs +0 -109
- package/src/condition-evaluator.mjs +0 -722
- package/src/dark-matter-core.mjs +0 -742
- package/src/define-hook.mjs +0 -213
- package/src/effect-sandbox-browser.mjs +0 -283
- package/src/effect-sandbox-worker.mjs +0 -170
- package/src/effect-sandbox.mjs +0 -517
- package/src/engines/index.mjs +0 -11
- package/src/engines/rdf-engine.mjs +0 -299
- package/src/file-resolver.mjs +0 -387
- package/src/hook-executor-batching.mjs +0 -277
- package/src/hook-executor.mjs +0 -870
- package/src/hook-management.mjs +0 -150
- package/src/ken-parliment.mjs +0 -119
- package/src/ken.mjs +0 -149
- package/src/knowledge-engine/builtin-rules.mjs +0 -190
- package/src/knowledge-engine/inference-engine.mjs +0 -418
- package/src/knowledge-engine/knowledge-engine.mjs +0 -317
- package/src/knowledge-engine/pattern-dsl.mjs +0 -142
- package/src/knowledge-engine/pattern-matcher.mjs +0 -215
- package/src/knowledge-engine/rules.mjs +0 -184
- package/src/knowledge-engine.mjs +0 -319
- package/src/knowledge-hook-engine.mjs +0 -360
- package/src/knowledge-substrate-core.mjs +0 -927
- package/src/lite.mjs +0 -222
- package/src/lockchain-writer.mjs +0 -602
- package/src/monitoring/andon-signals.mjs +0 -775
- package/src/parse.mjs +0 -290
- package/src/performance-optimizer.mjs +0 -678
- package/src/policy-pack.mjs +0 -572
- package/src/query-cache.mjs +0 -116
- package/src/query.mjs +0 -306
- package/src/reason.mjs +0 -350
- package/src/schemas.mjs +0 -1063
- package/src/security/error-sanitizer.mjs +0 -257
- package/src/security/path-validator.mjs +0 -194
- package/src/security/sandbox-restrictions.mjs +0 -331
- package/src/security-validator.mjs +0 -389
- package/src/store-cache.mjs +0 -137
- package/src/telemetry.mjs +0 -167
- package/src/utils/adaptive-monitor.mjs +0 -746
- package/src/utils/circuit-breaker.mjs +0 -513
- package/src/utils/edge-case-handler.mjs +0 -503
- package/src/utils/memory-manager.mjs +0 -498
- package/src/utils/ring-buffer.mjs +0 -282
- package/src/validate.mjs +0 -319
- package/src/validators/index.mjs +0 -338
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Chatman Engine - Unified Chatman Equation Integration
|
|
3
|
+
* @module knowledge-engine/chatman-engine
|
|
4
|
+
*
|
|
5
|
+
* @description
|
|
6
|
+
* Unified engine for executing Chatman Equation operations on the knowledge graph.
|
|
7
|
+
* Integrates operator, artifact generator, dark field detector, formation theorems,
|
|
8
|
+
* and all dynamics rules with OTEL observability and receipt generation.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { randomUUID } from 'crypto';
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { ChatmanOperator } from './chatman-operator.mjs';
|
|
14
|
+
import { ArtifactGenerator } from './artifact-generator.mjs';
|
|
15
|
+
import { DarkFieldDetector } from './dark-field-detector.mjs';
|
|
16
|
+
import { FormationTheorems } from './formation-theorems.mjs';
|
|
17
|
+
import { ChatmanConfigLoader } from './chatman-config-loader.mjs';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Engine options schema
|
|
21
|
+
*/
|
|
22
|
+
export const EngineOptionsSchema = z.object({
|
|
23
|
+
observableRatio: z.number().min(0).max(1).default(0.05),
|
|
24
|
+
closureThreshold: z.number().min(0).max(1).default(0.95),
|
|
25
|
+
enableReceipts: z.boolean().default(true),
|
|
26
|
+
tracer: z.function().optional(),
|
|
27
|
+
receiptGenerator: z.function().optional(),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Execution result schema
|
|
32
|
+
*/
|
|
33
|
+
export const ExecutionResultSchema = z.object({
|
|
34
|
+
id: z.string().uuid(),
|
|
35
|
+
operation: z.enum(['closure', 'artifact', 'detection', 'formation', 'full_pipeline']),
|
|
36
|
+
input: z.record(z.unknown()),
|
|
37
|
+
output: z.record(z.unknown()),
|
|
38
|
+
receipt: z
|
|
39
|
+
.object({
|
|
40
|
+
id: z.string().uuid(),
|
|
41
|
+
operation: z.string(),
|
|
42
|
+
timestamp: z.number(),
|
|
43
|
+
})
|
|
44
|
+
.optional(),
|
|
45
|
+
metrics: z.record(z.unknown()),
|
|
46
|
+
executedAt: z.number(),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Chatman Engine - Executes Chatman Equation operations
|
|
51
|
+
*/
|
|
52
|
+
export class ChatmanEngine {
|
|
53
|
+
/**
|
|
54
|
+
* Create a new Chatman engine
|
|
55
|
+
* @param {Object} [options] - Engine options
|
|
56
|
+
*/
|
|
57
|
+
constructor(options = {}) {
|
|
58
|
+
const opts = EngineOptionsSchema.parse(options);
|
|
59
|
+
|
|
60
|
+
this.tracer = opts.tracer;
|
|
61
|
+
this.receiptGenerator = opts.receiptGenerator;
|
|
62
|
+
this.enableReceipts = opts.enableReceipts;
|
|
63
|
+
|
|
64
|
+
// Initialize components
|
|
65
|
+
this.operator = new ChatmanOperator({
|
|
66
|
+
tracer: this.tracer,
|
|
67
|
+
observableRatio: opts.observableRatio,
|
|
68
|
+
closureThreshold: opts.closureThreshold,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this.artifactGenerator = new ArtifactGenerator({
|
|
72
|
+
tracer: this.tracer,
|
|
73
|
+
receiptGenerator: this.receiptGenerator,
|
|
74
|
+
observableRatio: opts.observableRatio,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
this.darkFieldDetector = new DarkFieldDetector({
|
|
78
|
+
tracer: this.tracer,
|
|
79
|
+
targetRatio: 1 - opts.observableRatio,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
this.formationTheorems = new FormationTheorems({
|
|
83
|
+
tracer: this.tracer,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
this.configLoader = new ChatmanConfigLoader({
|
|
87
|
+
tracer: this.tracer,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
this.metrics = {
|
|
91
|
+
operationsExecuted: 0,
|
|
92
|
+
receiptsGenerated: 0,
|
|
93
|
+
averageExecutionTime: 0,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Execute closure operation: A = μ(O)
|
|
99
|
+
* @param {Object} observable - Observable pattern
|
|
100
|
+
* @param {Object} [options] - Execution options
|
|
101
|
+
* @returns {Promise<Object>} Execution result
|
|
102
|
+
*/
|
|
103
|
+
async executeClosure(observable, options = {}) {
|
|
104
|
+
const span = this.tracer?.startSpan?.('chatman.engine.execute_closure');
|
|
105
|
+
const startTime = Date.now();
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
span?.setAttribute?.('observable.type', observable.type);
|
|
109
|
+
|
|
110
|
+
const closure = await this.operator.apply(observable);
|
|
111
|
+
const receipt = this._createReceipt('closure', { observable, closure });
|
|
112
|
+
|
|
113
|
+
const result = {
|
|
114
|
+
id: randomUUID(),
|
|
115
|
+
operation: 'closure',
|
|
116
|
+
input: { observable },
|
|
117
|
+
output: { closure },
|
|
118
|
+
receipt: this.enableReceipts ? receipt : undefined,
|
|
119
|
+
metrics: this.operator.getMetrics(),
|
|
120
|
+
executedAt: Date.now(),
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
this._updateMetrics(startTime);
|
|
124
|
+
|
|
125
|
+
span?.addEvent?.('closure_executed', {
|
|
126
|
+
'result.id': result.id,
|
|
127
|
+
'result.completeness': closure.completeness,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return result;
|
|
131
|
+
} catch (error) {
|
|
132
|
+
span?.recordException?.(error);
|
|
133
|
+
span?.setStatus?.({ code: 2, message: error.message });
|
|
134
|
+
throw error;
|
|
135
|
+
} finally {
|
|
136
|
+
span?.end?.();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Execute artifact generation: A = μ(O)
|
|
142
|
+
* @param {Object} observable - Observable pattern
|
|
143
|
+
* @param {Object} [options] - Execution options
|
|
144
|
+
* @returns {Promise<Object>} Execution result
|
|
145
|
+
*/
|
|
146
|
+
async executeArtifact(observable, options = {}) {
|
|
147
|
+
const span = this.tracer?.startSpan?.('chatman.engine.execute_artifact');
|
|
148
|
+
const startTime = Date.now();
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
span?.setAttribute?.('observable.type', observable.type);
|
|
152
|
+
|
|
153
|
+
const artifact = await this.artifactGenerator.generate(observable, {
|
|
154
|
+
includeReceipt: this.enableReceipts,
|
|
155
|
+
...options,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const receipt = this._createReceipt('artifact', { observable, artifact });
|
|
159
|
+
|
|
160
|
+
const result = {
|
|
161
|
+
id: randomUUID(),
|
|
162
|
+
operation: 'artifact',
|
|
163
|
+
input: { observable },
|
|
164
|
+
output: { artifact },
|
|
165
|
+
receipt: this.enableReceipts ? receipt : undefined,
|
|
166
|
+
metrics: this.artifactGenerator.getMetrics(),
|
|
167
|
+
executedAt: Date.now(),
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
this._updateMetrics(startTime);
|
|
171
|
+
|
|
172
|
+
span?.addEvent?.('artifact_executed', {
|
|
173
|
+
'result.id': result.id,
|
|
174
|
+
'artifact.id': artifact.id,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
return result;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
span?.recordException?.(error);
|
|
180
|
+
span?.setStatus?.({ code: 2, message: error.message });
|
|
181
|
+
throw error;
|
|
182
|
+
} finally {
|
|
183
|
+
span?.end?.();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Execute dark field detection
|
|
189
|
+
* @param {Object} observable - Observable pattern
|
|
190
|
+
* @param {Object} [options] - Execution options
|
|
191
|
+
* @returns {Promise<Object>} Execution result
|
|
192
|
+
*/
|
|
193
|
+
async executeDetection(observable, options = {}) {
|
|
194
|
+
const span = this.tracer?.startSpan?.('chatman.engine.execute_detection');
|
|
195
|
+
const startTime = Date.now();
|
|
196
|
+
|
|
197
|
+
try {
|
|
198
|
+
span?.setAttribute?.('observable.type', observable.type);
|
|
199
|
+
|
|
200
|
+
const detection = await this.darkFieldDetector.detect(observable, options);
|
|
201
|
+
const receipt = this._createReceipt('detection', { observable, detection });
|
|
202
|
+
|
|
203
|
+
const result = {
|
|
204
|
+
id: randomUUID(),
|
|
205
|
+
operation: 'detection',
|
|
206
|
+
input: { observable },
|
|
207
|
+
output: { detection },
|
|
208
|
+
receipt: this.enableReceipts ? receipt : undefined,
|
|
209
|
+
metrics: this.darkFieldDetector.getMetrics(),
|
|
210
|
+
executedAt: Date.now(),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
this._updateMetrics(startTime);
|
|
214
|
+
|
|
215
|
+
span?.addEvent?.('detection_executed', {
|
|
216
|
+
'result.id': result.id,
|
|
217
|
+
'detection.id': detection.id,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
return result;
|
|
221
|
+
} catch (error) {
|
|
222
|
+
span?.recordException?.(error);
|
|
223
|
+
span?.setStatus?.({ code: 2, message: error.message });
|
|
224
|
+
throw error;
|
|
225
|
+
} finally {
|
|
226
|
+
span?.end?.();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Execute formation theorem derivation
|
|
232
|
+
* @param {Object} artifact - Artifact with observable and dark field
|
|
233
|
+
* @param {Object} [options] - Execution options
|
|
234
|
+
* @returns {Promise<Object>} Execution result
|
|
235
|
+
*/
|
|
236
|
+
async executeFormation(artifact, options = {}) {
|
|
237
|
+
const span = this.tracer?.startSpan?.('chatman.engine.execute_formation');
|
|
238
|
+
const startTime = Date.now();
|
|
239
|
+
|
|
240
|
+
try {
|
|
241
|
+
span?.setAttribute?.('artifact.type', artifact.type);
|
|
242
|
+
span?.setAttribute?.('theorem', options.theorem || 'emergence');
|
|
243
|
+
|
|
244
|
+
const formation = await this.formationTheorems.derive(artifact, options);
|
|
245
|
+
const receipt = this._createReceipt('formation', { artifact, formation });
|
|
246
|
+
|
|
247
|
+
const result = {
|
|
248
|
+
id: randomUUID(),
|
|
249
|
+
operation: 'formation',
|
|
250
|
+
input: { artifact },
|
|
251
|
+
output: { formation },
|
|
252
|
+
receipt: this.enableReceipts ? receipt : undefined,
|
|
253
|
+
metrics: this.formationTheorems.getMetrics(),
|
|
254
|
+
executedAt: Date.now(),
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
this._updateMetrics(startTime);
|
|
258
|
+
|
|
259
|
+
span?.addEvent?.('formation_executed', {
|
|
260
|
+
'result.id': result.id,
|
|
261
|
+
'formation.id': formation.id,
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
return result;
|
|
265
|
+
} catch (error) {
|
|
266
|
+
span?.recordException?.(error);
|
|
267
|
+
span?.setStatus?.({ code: 2, message: error.message });
|
|
268
|
+
throw error;
|
|
269
|
+
} finally {
|
|
270
|
+
span?.end?.();
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Execute full Chatman pipeline: Observable → Artifact → Formation
|
|
276
|
+
* @param {Object} observable - Observable pattern
|
|
277
|
+
* @param {Object} [options] - Execution options
|
|
278
|
+
* @returns {Promise<Object>} Execution result
|
|
279
|
+
*/
|
|
280
|
+
async executePipeline(observable, options = {}) {
|
|
281
|
+
const span = this.tracer?.startSpan?.('chatman.engine.execute_pipeline');
|
|
282
|
+
const startTime = Date.now();
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
span?.setAttribute?.('observable.type', observable.type);
|
|
286
|
+
|
|
287
|
+
// Step 1: Generate artifact
|
|
288
|
+
const artifactResult = await this.executeArtifact(observable, options);
|
|
289
|
+
|
|
290
|
+
// Step 2: Detect dark field
|
|
291
|
+
const detectionResult = await this.executeDetection(observable, options);
|
|
292
|
+
|
|
293
|
+
// Step 3: Derive formation
|
|
294
|
+
const formationResult = await this.executeFormation(
|
|
295
|
+
artifactResult.output.artifact,
|
|
296
|
+
options
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const receipt = this._createReceipt('full_pipeline', {
|
|
300
|
+
observable,
|
|
301
|
+
artifact: artifactResult.output.artifact,
|
|
302
|
+
detection: detectionResult.output.detection,
|
|
303
|
+
formation: formationResult.output.formation,
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const result = {
|
|
307
|
+
id: randomUUID(),
|
|
308
|
+
operation: 'full_pipeline',
|
|
309
|
+
input: { observable },
|
|
310
|
+
output: {
|
|
311
|
+
artifact: artifactResult.output.artifact,
|
|
312
|
+
detection: detectionResult.output.detection,
|
|
313
|
+
formation: formationResult.output.formation,
|
|
314
|
+
},
|
|
315
|
+
receipt: this.enableReceipts ? receipt : undefined,
|
|
316
|
+
metrics: {
|
|
317
|
+
operator: this.operator.getMetrics(),
|
|
318
|
+
artifactGenerator: this.artifactGenerator.getMetrics(),
|
|
319
|
+
darkFieldDetector: this.darkFieldDetector.getMetrics(),
|
|
320
|
+
formationTheorems: this.formationTheorems.getMetrics(),
|
|
321
|
+
},
|
|
322
|
+
executedAt: Date.now(),
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
this._updateMetrics(startTime);
|
|
326
|
+
|
|
327
|
+
span?.addEvent?.('pipeline_executed', {
|
|
328
|
+
'result.id': result.id,
|
|
329
|
+
'pipeline.duration_ms': Date.now() - startTime,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
return result;
|
|
333
|
+
} catch (error) {
|
|
334
|
+
span?.recordException?.(error);
|
|
335
|
+
span?.setStatus?.({ code: 2, message: error.message });
|
|
336
|
+
throw error;
|
|
337
|
+
} finally {
|
|
338
|
+
span?.end?.();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Load configuration from TOML file
|
|
344
|
+
* @param {string} configPath - Path to config file
|
|
345
|
+
* @param {Object} [options] - Load options
|
|
346
|
+
* @returns {Promise<Object>} Loaded configuration
|
|
347
|
+
*/
|
|
348
|
+
async loadConfig(configPath, options = {}) {
|
|
349
|
+
return this.configLoader.load(configPath, options);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Create receipt for operation
|
|
354
|
+
* @param {string} operation - Operation name
|
|
355
|
+
* @param {Object} data - Operation data
|
|
356
|
+
* @returns {Object} Receipt
|
|
357
|
+
* @private
|
|
358
|
+
*/
|
|
359
|
+
_createReceipt(operation, data) {
|
|
360
|
+
if (this.receiptGenerator) {
|
|
361
|
+
return this.receiptGenerator({
|
|
362
|
+
operation: `chatman_${operation}`,
|
|
363
|
+
entityType: 'ChatmanOperation',
|
|
364
|
+
entityId: randomUUID(),
|
|
365
|
+
data,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const receipt = {
|
|
370
|
+
id: randomUUID(),
|
|
371
|
+
operation: `chatman_${operation}`,
|
|
372
|
+
timestamp: Date.now(),
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
if (this.enableReceipts) {
|
|
376
|
+
this.metrics.receiptsGenerated++;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return receipt;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Update engine metrics
|
|
384
|
+
* @param {number} startTime - Operation start time
|
|
385
|
+
* @private
|
|
386
|
+
*/
|
|
387
|
+
_updateMetrics(startTime) {
|
|
388
|
+
this.metrics.operationsExecuted++;
|
|
389
|
+
const duration = Date.now() - startTime;
|
|
390
|
+
this.metrics.averageExecutionTime =
|
|
391
|
+
(this.metrics.averageExecutionTime * (this.metrics.operationsExecuted - 1) +
|
|
392
|
+
duration) /
|
|
393
|
+
this.metrics.operationsExecuted;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Get engine metrics
|
|
398
|
+
* @returns {Object} Metrics
|
|
399
|
+
*/
|
|
400
|
+
getMetrics() {
|
|
401
|
+
return {
|
|
402
|
+
...this.metrics,
|
|
403
|
+
components: {
|
|
404
|
+
operator: this.operator.getMetrics(),
|
|
405
|
+
artifactGenerator: this.artifactGenerator.getMetrics(),
|
|
406
|
+
darkFieldDetector: this.darkFieldDetector.getMetrics(),
|
|
407
|
+
formationTheorems: this.formationTheorems.getMetrics(),
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Reset all metrics
|
|
414
|
+
*/
|
|
415
|
+
resetMetrics() {
|
|
416
|
+
this.metrics = {
|
|
417
|
+
operationsExecuted: 0,
|
|
418
|
+
receiptsGenerated: 0,
|
|
419
|
+
averageExecutionTime: 0,
|
|
420
|
+
};
|
|
421
|
+
this.operator.resetMetrics();
|
|
422
|
+
this.artifactGenerator.resetMetrics();
|
|
423
|
+
this.darkFieldDetector.resetMetrics();
|
|
424
|
+
this.formationTheorems.resetMetrics();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Create a Chatman engine instance
|
|
430
|
+
* @param {Object} [options] - Engine options
|
|
431
|
+
* @returns {ChatmanEngine} Engine instance
|
|
432
|
+
*/
|
|
433
|
+
export function createChatmanEngine(options = {}) {
|
|
434
|
+
return new ChatmanEngine(options);
|
|
435
|
+
}
|