@soulcraft/brainy 6.2.9 → 6.3.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.
- package/CHANGELOG.md +21 -0
- package/dist/brainy.d.ts +55 -0
- package/dist/brainy.js +104 -7
- package/dist/graph/graphAdjacencyIndex.d.ts +7 -0
- package/dist/graph/graphAdjacencyIndex.js +42 -0
- package/dist/storage/baseStorage.d.ts +7 -0
- package/dist/storage/baseStorage.js +31 -38
- package/dist/versioning/VersionIndex.d.ts +42 -47
- package/dist/versioning/VersionIndex.js +141 -166
- package/dist/versioning/VersionManager.d.ts +12 -6
- package/dist/versioning/VersionManager.js +26 -8
- package/dist/versioning/VersionStorage.d.ts +25 -15
- package/dist/versioning/VersionStorage.js +49 -65
- package/dist/vfs/PathResolver.d.ts +6 -0
- package/dist/vfs/PathResolver.js +20 -0
- package/dist/vfs/semantic/SemanticPathResolver.d.ts +6 -0
- package/dist/vfs/semantic/SemanticPathResolver.js +11 -0
- package/package.json +1 -1
- package/dist/augmentations/KnowledgeAugmentation.d.ts +0 -40
- package/dist/augmentations/KnowledgeAugmentation.js +0 -251
- package/dist/importManager.d.ts +0 -78
- package/dist/importManager.js +0 -267
- package/dist/query/typeInference.d.ts +0 -158
- package/dist/query/typeInference.js +0 -760
- package/dist/storage/adapters/typeAwareStorageAdapter.d.ts +0 -252
- package/dist/storage/adapters/typeAwareStorageAdapter.js +0 -814
- package/dist/types/brainyDataInterface.d.ts +0 -52
- package/dist/types/brainyDataInterface.js +0 -10
- package/dist/vfs/ConceptSystem.d.ts +0 -203
- package/dist/vfs/ConceptSystem.js +0 -545
- package/dist/vfs/EntityManager.d.ts +0 -75
- package/dist/vfs/EntityManager.js +0 -216
- package/dist/vfs/EventRecorder.d.ts +0 -84
- package/dist/vfs/EventRecorder.js +0 -269
- package/dist/vfs/GitBridge.d.ts +0 -167
- package/dist/vfs/GitBridge.js +0 -537
- package/dist/vfs/KnowledgeLayer.d.ts +0 -35
- package/dist/vfs/KnowledgeLayer.js +0 -443
- package/dist/vfs/PersistentEntitySystem.d.ts +0 -165
- package/dist/vfs/PersistentEntitySystem.js +0 -503
- package/dist/vfs/SemanticVersioning.d.ts +0 -105
- package/dist/vfs/SemanticVersioning.js +0 -309
|
@@ -1,760 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type Inference System - Phase 3: Type-First Query Optimization
|
|
3
|
-
*
|
|
4
|
-
* Automatically infers NounTypes from natural language queries using keyword-based
|
|
5
|
-
* heuristics for fast O(1) type detection.
|
|
6
|
-
*
|
|
7
|
-
* Performance Guarantee: < 1ms per query
|
|
8
|
-
* Accuracy Target: > 80%
|
|
9
|
-
*
|
|
10
|
-
* Examples:
|
|
11
|
-
* - "Find engineers in San Francisco" → [Person, Location]
|
|
12
|
-
* - "Show documents about AI" → [Document, Concept]
|
|
13
|
-
* - "List companies in tech sector" → [Organization, Topic]
|
|
14
|
-
*/
|
|
15
|
-
import { NounType } from '../types/graphTypes.js';
|
|
16
|
-
import { prodLog } from '../utils/logger.js';
|
|
17
|
-
/**
|
|
18
|
-
* Type Inference System
|
|
19
|
-
*
|
|
20
|
-
* Uses keyword matching for fast type detection from natural language.
|
|
21
|
-
* Designed for billion-scale performance with minimal latency.
|
|
22
|
-
*/
|
|
23
|
-
export class TypeInferenceSystem {
|
|
24
|
-
constructor(config) {
|
|
25
|
-
this.typeEmbeddings = null;
|
|
26
|
-
this.embedder = null; // Lazy-loaded TransformerEmbedding
|
|
27
|
-
this.config = {
|
|
28
|
-
minConfidence: config?.minConfidence ?? 0.4,
|
|
29
|
-
maxTypes: config?.maxTypes ?? 5,
|
|
30
|
-
debug: config?.debug ?? false,
|
|
31
|
-
enableVectorFallback: config?.enableVectorFallback ?? false,
|
|
32
|
-
fallbackConfidenceThreshold: config?.fallbackConfidenceThreshold ?? 0.7,
|
|
33
|
-
vectorThreshold: config?.vectorThreshold ?? 0.5
|
|
34
|
-
};
|
|
35
|
-
this.keywordMap = this.buildKeywordMap();
|
|
36
|
-
this.phraseMap = this.buildPhraseMap();
|
|
37
|
-
// Load pre-compiled type embeddings if vector fallback is enabled
|
|
38
|
-
// Note: This is async but we don't await in constructor
|
|
39
|
-
// The embeddings will be loaded before first inferTypesAsync() call
|
|
40
|
-
if (this.config.enableVectorFallback) {
|
|
41
|
-
this.loadTypeEmbeddings().catch(err => {
|
|
42
|
-
prodLog.warn(`Failed to load type embeddings in constructor: ${err.message}`);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
prodLog.info(`TypeInferenceSystem initialized: ${this.keywordMap.size} keywords, ${this.phraseMap.size} phrases` +
|
|
46
|
-
(this.config.enableVectorFallback ? ', vector fallback enabled' : ''));
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Infer noun types from a natural language query (synchronous keyword matching only)
|
|
50
|
-
* For hybrid mode with vector fallback, use inferTypesAsync()
|
|
51
|
-
*
|
|
52
|
-
* @param query - Natural language query string
|
|
53
|
-
* @returns Array of type inferences sorted by confidence (highest first)
|
|
54
|
-
*/
|
|
55
|
-
inferTypes(query) {
|
|
56
|
-
const startTime = performance.now();
|
|
57
|
-
if (!query || query.trim().length === 0) {
|
|
58
|
-
return [];
|
|
59
|
-
}
|
|
60
|
-
// Keyword matching only (fast path - O(1) lookup)
|
|
61
|
-
const results = this.inferTypesViaKeywords(query);
|
|
62
|
-
const elapsed = performance.now() - startTime;
|
|
63
|
-
if (this.config.debug) {
|
|
64
|
-
prodLog.debug(`Type inference (keyword): ${results.length} types inferred in ${elapsed.toFixed(2)}ms`);
|
|
65
|
-
}
|
|
66
|
-
return results;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Infer noun types with hybrid approach: keyword matching + optional vector fallback
|
|
70
|
-
* This is the async version that supports vector similarity fallback
|
|
71
|
-
*
|
|
72
|
-
* @param query - Natural language query string
|
|
73
|
-
* @returns Promise resolving to array of type inferences
|
|
74
|
-
*/
|
|
75
|
-
async inferTypesAsync(query) {
|
|
76
|
-
const startTime = performance.now();
|
|
77
|
-
if (!query || query.trim().length === 0) {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
// Step 1: Try keyword matching (fast path - O(1) lookup)
|
|
81
|
-
const keywordResults = this.inferTypesViaKeywords(query);
|
|
82
|
-
// Step 2: Check if we should use vector fallback
|
|
83
|
-
const shouldUseFallback = this.config.enableVectorFallback && (keywordResults.length === 0 ||
|
|
84
|
-
keywordResults[0].confidence < this.config.fallbackConfidenceThreshold);
|
|
85
|
-
if (!shouldUseFallback) {
|
|
86
|
-
// Fast path: Return keyword results immediately
|
|
87
|
-
const elapsed = performance.now() - startTime;
|
|
88
|
-
if (this.config.debug) {
|
|
89
|
-
prodLog.debug(`Type inference (keyword): ${keywordResults.length} types inferred in ${elapsed.toFixed(2)}ms`);
|
|
90
|
-
}
|
|
91
|
-
return keywordResults;
|
|
92
|
-
}
|
|
93
|
-
// Slow path: Use vector similarity fallback (async)
|
|
94
|
-
return this.inferTypesWithFallback(query, keywordResults, startTime);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Internal: Keyword-based type inference (synchronous, fast)
|
|
98
|
-
*/
|
|
99
|
-
inferTypesViaKeywords(query) {
|
|
100
|
-
// Normalize query
|
|
101
|
-
const normalized = query.toLowerCase().trim();
|
|
102
|
-
// Track inferred types with scores
|
|
103
|
-
const typeScores = new Map();
|
|
104
|
-
// Phase 1: Multi-word phrase matching (highest confidence)
|
|
105
|
-
this.matchPhrases(normalized, typeScores);
|
|
106
|
-
// Phase 2: Single keyword matching
|
|
107
|
-
this.matchKeywords(normalized, typeScores);
|
|
108
|
-
// Convert to result array
|
|
109
|
-
const results = [];
|
|
110
|
-
for (const [type, data] of typeScores) {
|
|
111
|
-
if (data.confidence >= this.config.minConfidence) {
|
|
112
|
-
results.push({
|
|
113
|
-
type,
|
|
114
|
-
confidence: data.confidence,
|
|
115
|
-
matchedKeywords: Array.from(data.keywords)
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// Sort by confidence (descending)
|
|
120
|
-
results.sort((a, b) => b.confidence - a.confidence);
|
|
121
|
-
// Limit results
|
|
122
|
-
return results.slice(0, this.config.maxTypes);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Internal: Hybrid inference with vector fallback (asynchronous)
|
|
126
|
-
*/
|
|
127
|
-
async inferTypesWithFallback(query, keywordResults, startTime) {
|
|
128
|
-
if (this.config.debug) {
|
|
129
|
-
prodLog.debug(`Type inference: Low keyword confidence (${keywordResults.length > 0 ? keywordResults[0].confidence.toFixed(2) : '0.00'}), triggering vector fallback`);
|
|
130
|
-
}
|
|
131
|
-
// Use vector similarity fallback
|
|
132
|
-
const vectorResults = await this.inferTypesViaVectorSimilarity(query);
|
|
133
|
-
// Merge keyword and vector results
|
|
134
|
-
const mergedResults = this.mergeResults(keywordResults, vectorResults);
|
|
135
|
-
const elapsed = performance.now() - startTime;
|
|
136
|
-
if (this.config.debug) {
|
|
137
|
-
prodLog.debug(`Type inference (hybrid): ${mergedResults.length} types inferred in ${elapsed.toFixed(2)}ms ` +
|
|
138
|
-
`(${keywordResults.length} keyword, ${vectorResults.length} vector)`);
|
|
139
|
-
}
|
|
140
|
-
// Performance warning (only for fallback path)
|
|
141
|
-
if (elapsed > 100) {
|
|
142
|
-
prodLog.warn(`Type inference slow (vector fallback): Took ${elapsed.toFixed(2)}ms`);
|
|
143
|
-
}
|
|
144
|
-
return mergedResults;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Match multi-word phrases in query
|
|
148
|
-
*/
|
|
149
|
-
matchPhrases(query, typeScores) {
|
|
150
|
-
for (const [phrase, entry] of this.phraseMap) {
|
|
151
|
-
if (query.includes(phrase)) {
|
|
152
|
-
for (const type of entry.types) {
|
|
153
|
-
this.updateTypeScore(type, entry.confidence, phrase, typeScores);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Match individual keywords in query
|
|
160
|
-
*/
|
|
161
|
-
matchKeywords(query, typeScores) {
|
|
162
|
-
// Tokenize query (split on non-alphanumeric)
|
|
163
|
-
const tokens = query.split(/[^a-z0-9]+/).filter(t => t.length > 0);
|
|
164
|
-
for (const token of tokens) {
|
|
165
|
-
let entry = this.keywordMap.get(token);
|
|
166
|
-
let matchedKeyword = token;
|
|
167
|
-
// If no exact match, try singular form (simple plural handling)
|
|
168
|
-
if (!entry && token.endsWith('s') && token.length > 2) {
|
|
169
|
-
const singular = token.slice(0, -1);
|
|
170
|
-
entry = this.keywordMap.get(singular);
|
|
171
|
-
if (entry)
|
|
172
|
-
matchedKeyword = singular;
|
|
173
|
-
}
|
|
174
|
-
// If still no match and ends with 'es', try removing 'es'
|
|
175
|
-
if (!entry && token.endsWith('es') && token.length > 3) {
|
|
176
|
-
const singular = token.slice(0, -2);
|
|
177
|
-
entry = this.keywordMap.get(singular);
|
|
178
|
-
if (entry)
|
|
179
|
-
matchedKeyword = singular;
|
|
180
|
-
}
|
|
181
|
-
// If still no match and ends with 'ies', try changing to 'y'
|
|
182
|
-
if (!entry && token.endsWith('ies') && token.length > 4) {
|
|
183
|
-
const singular = token.slice(0, -3) + 'y';
|
|
184
|
-
entry = this.keywordMap.get(singular);
|
|
185
|
-
if (entry)
|
|
186
|
-
matchedKeyword = singular;
|
|
187
|
-
}
|
|
188
|
-
// If still no match, try fuzzy matching for typos (edit distance <= 1)
|
|
189
|
-
if (!entry && token.length >= 5) {
|
|
190
|
-
const fuzzyMatch = this.findFuzzyKeywordMatch(token);
|
|
191
|
-
if (fuzzyMatch) {
|
|
192
|
-
entry = fuzzyMatch.entry;
|
|
193
|
-
matchedKeyword = `${token}→${fuzzyMatch.keyword}`;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
if (entry) {
|
|
197
|
-
for (const type of entry.types) {
|
|
198
|
-
this.updateTypeScore(type, entry.confidence * (matchedKeyword.includes('→') ? 0.85 : 1.0), // Reduce confidence for fuzzy matches
|
|
199
|
-
matchedKeyword, typeScores);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Find closest keyword using edit distance (for typo correction)
|
|
206
|
-
* Allows edit distance 1-2 depending on word length
|
|
207
|
-
*/
|
|
208
|
-
findFuzzyKeywordMatch(token) {
|
|
209
|
-
// Only attempt fuzzy matching for words 5+ characters
|
|
210
|
-
if (token.length < 5)
|
|
211
|
-
return null;
|
|
212
|
-
// Determine max edit distance based on word length
|
|
213
|
-
// Shorter words (5-7 chars): distance <= 1
|
|
214
|
-
// Longer words (8+ chars): distance <= 2
|
|
215
|
-
const maxDistance = token.length >= 8 ? 2 : 1;
|
|
216
|
-
for (const [keyword, entry] of this.keywordMap) {
|
|
217
|
-
// Only match keywords of similar length (±2 for distance 2, ±1 for distance 1)
|
|
218
|
-
if (Math.abs(keyword.length - token.length) > maxDistance)
|
|
219
|
-
continue;
|
|
220
|
-
// Calculate edit distance
|
|
221
|
-
const distance = this.levenshteinDistance(token, keyword);
|
|
222
|
-
// Accept if within threshold
|
|
223
|
-
if (distance > 0 && distance <= maxDistance) {
|
|
224
|
-
return { keyword, entry };
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return null;
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Calculate Levenshtein (edit) distance between two strings
|
|
231
|
-
*/
|
|
232
|
-
levenshteinDistance(a, b) {
|
|
233
|
-
const matrix = [];
|
|
234
|
-
for (let i = 0; i <= b.length; i++) {
|
|
235
|
-
matrix[i] = [i];
|
|
236
|
-
}
|
|
237
|
-
for (let j = 0; j <= a.length; j++) {
|
|
238
|
-
matrix[0][j] = j;
|
|
239
|
-
}
|
|
240
|
-
for (let i = 1; i <= b.length; i++) {
|
|
241
|
-
for (let j = 1; j <= a.length; j++) {
|
|
242
|
-
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
243
|
-
matrix[i][j] = matrix[i - 1][j - 1];
|
|
244
|
-
}
|
|
245
|
-
else {
|
|
246
|
-
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
|
|
247
|
-
matrix[i][j - 1] + 1, // insertion
|
|
248
|
-
matrix[i - 1][j] + 1 // deletion
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return matrix[b.length][a.length];
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Update type score with new match
|
|
257
|
-
*/
|
|
258
|
-
updateTypeScore(type, confidence, keyword, typeScores) {
|
|
259
|
-
const existing = typeScores.get(type);
|
|
260
|
-
if (existing) {
|
|
261
|
-
// Boost confidence for multiple matches (max 1.0)
|
|
262
|
-
existing.confidence = Math.min(1.0, existing.confidence + confidence * 0.2);
|
|
263
|
-
existing.keywords.add(keyword);
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
typeScores.set(type, {
|
|
267
|
-
confidence,
|
|
268
|
-
keywords: new Set([keyword])
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Load pre-compiled type embeddings from embeddedTypeEmbeddings.ts
|
|
274
|
-
*/
|
|
275
|
-
async loadTypeEmbeddings() {
|
|
276
|
-
try {
|
|
277
|
-
// Dynamically import to avoid loading if not needed
|
|
278
|
-
const module = await import('../neural/embeddedTypeEmbeddings.js');
|
|
279
|
-
this.typeEmbeddings = module.getNounTypeEmbeddings();
|
|
280
|
-
if (this.config.debug) {
|
|
281
|
-
prodLog.debug(`Loaded ${this.typeEmbeddings?.size || 0} pre-compiled type embeddings for vector fallback`);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
catch (error) {
|
|
285
|
-
prodLog.warn(`Failed to load type embeddings: ${error.message}`);
|
|
286
|
-
this.config.enableVectorFallback = false;
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Lazy-load TransformerEmbedding model (only when vector fallback is triggered)
|
|
291
|
-
*/
|
|
292
|
-
async loadEmbedder() {
|
|
293
|
-
if (this.embedder) {
|
|
294
|
-
return this.embedder;
|
|
295
|
-
}
|
|
296
|
-
try {
|
|
297
|
-
const { TransformerEmbedding } = await import('../utils/embedding.js');
|
|
298
|
-
const embedder = new TransformerEmbedding({ verbose: false });
|
|
299
|
-
await embedder.init();
|
|
300
|
-
this.embedder = embedder;
|
|
301
|
-
if (this.config.debug) {
|
|
302
|
-
prodLog.debug('TransformerEmbedding model loaded for vector fallback');
|
|
303
|
-
}
|
|
304
|
-
return embedder;
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
prodLog.error(`Failed to load embedder: ${error.message}`);
|
|
308
|
-
throw new Error(`Cannot use vector fallback: ${error.message}`);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Calculate cosine similarity between two vectors
|
|
313
|
-
*/
|
|
314
|
-
cosineSimilarity(a, b) {
|
|
315
|
-
if (!a || !b || a.length !== b.length)
|
|
316
|
-
return 0;
|
|
317
|
-
let dotProduct = 0;
|
|
318
|
-
let normA = 0;
|
|
319
|
-
let normB = 0;
|
|
320
|
-
for (let i = 0; i < a.length; i++) {
|
|
321
|
-
dotProduct += a[i] * b[i];
|
|
322
|
-
normA += a[i] * a[i];
|
|
323
|
-
normB += b[i] * b[i];
|
|
324
|
-
}
|
|
325
|
-
const denominator = Math.sqrt(normA) * Math.sqrt(normB);
|
|
326
|
-
return denominator === 0 ? 0 : dotProduct / denominator;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Infer types using vector similarity against pre-compiled type embeddings
|
|
330
|
-
*/
|
|
331
|
-
async inferTypesViaVectorSimilarity(query) {
|
|
332
|
-
const startTime = performance.now();
|
|
333
|
-
try {
|
|
334
|
-
// Ensure type embeddings are loaded (wait if still loading)
|
|
335
|
-
if (!this.typeEmbeddings) {
|
|
336
|
-
if (this.config.enableVectorFallback) {
|
|
337
|
-
// Try loading once more in case constructor load failed
|
|
338
|
-
await this.loadTypeEmbeddings();
|
|
339
|
-
}
|
|
340
|
-
if (!this.typeEmbeddings) {
|
|
341
|
-
prodLog.warn('Type embeddings not loaded, cannot use vector fallback');
|
|
342
|
-
return [];
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
// Lazy-load embedder if not already loaded
|
|
346
|
-
const embedder = await this.loadEmbedder();
|
|
347
|
-
// Generate query embedding
|
|
348
|
-
const queryEmbedding = await embedder.embed(query);
|
|
349
|
-
// Calculate similarity against all type embeddings
|
|
350
|
-
const similarities = [];
|
|
351
|
-
for (const [type, typeEmbedding] of this.typeEmbeddings) {
|
|
352
|
-
const similarity = this.cosineSimilarity(queryEmbedding, typeEmbedding);
|
|
353
|
-
if (similarity >= this.config.vectorThreshold) {
|
|
354
|
-
similarities.push({
|
|
355
|
-
type,
|
|
356
|
-
confidence: similarity,
|
|
357
|
-
matchedKeywords: ['<vector-similarity>']
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
// Sort by confidence (descending)
|
|
362
|
-
similarities.sort((a, b) => b.confidence - a.confidence);
|
|
363
|
-
const elapsed = performance.now() - startTime;
|
|
364
|
-
if (this.config.debug) {
|
|
365
|
-
prodLog.debug(`Vector similarity inference complete: ${similarities.length} types found in ${elapsed.toFixed(2)}ms`);
|
|
366
|
-
}
|
|
367
|
-
return similarities.slice(0, this.config.maxTypes);
|
|
368
|
-
}
|
|
369
|
-
catch (error) {
|
|
370
|
-
prodLog.error(`Vector similarity inference failed: ${error.message}`);
|
|
371
|
-
return [];
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Merge keyword-based and vector-based results
|
|
376
|
-
* Prioritizes keyword results (explicit matches) over vector results (semantic matches)
|
|
377
|
-
*/
|
|
378
|
-
mergeResults(keywordResults, vectorResults) {
|
|
379
|
-
const merged = new Map();
|
|
380
|
-
// Add keyword results first (higher priority, boost confidence)
|
|
381
|
-
for (const result of keywordResults) {
|
|
382
|
-
merged.set(result.type, {
|
|
383
|
-
...result,
|
|
384
|
-
confidence: Math.min(1.0, result.confidence * 1.2) // Boost keyword matches by 20%
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
// Add vector results if not already present
|
|
388
|
-
for (const result of vectorResults) {
|
|
389
|
-
if (!merged.has(result.type)) {
|
|
390
|
-
merged.set(result.type, result);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
// Convert to array and sort by confidence
|
|
394
|
-
const results = Array.from(merged.values())
|
|
395
|
-
.sort((a, b) => b.confidence - a.confidence)
|
|
396
|
-
.slice(0, this.config.maxTypes);
|
|
397
|
-
return results;
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Build keyword dictionary for single-word matching
|
|
401
|
-
*/
|
|
402
|
-
buildKeywordMap() {
|
|
403
|
-
const map = new Map();
|
|
404
|
-
// Helper to add keywords
|
|
405
|
-
const add = (keywords, types, confidence) => {
|
|
406
|
-
for (const keyword of keywords) {
|
|
407
|
-
map.set(keyword, { types, confidence });
|
|
408
|
-
}
|
|
409
|
-
};
|
|
410
|
-
// Person (100+ keywords)
|
|
411
|
-
add([
|
|
412
|
-
// Roles - Professional
|
|
413
|
-
'person', 'people', 'individual', 'human',
|
|
414
|
-
'user', 'employee', 'worker', 'staff', 'personnel', 'member', 'team',
|
|
415
|
-
'engineer', 'developer', 'programmer', 'coder', 'architect', 'designer',
|
|
416
|
-
'manager', 'director', 'executive', 'leader', 'supervisor', 'coordinator',
|
|
417
|
-
'ceo', 'cto', 'cfo', 'coo', 'vp', 'president', 'founder', 'owner',
|
|
418
|
-
'analyst', 'consultant', 'specialist', 'expert', 'professional',
|
|
419
|
-
'technician', 'operator', 'administrator', 'assistant', 'associate',
|
|
420
|
-
// Roles - Specific Professions (Medical)
|
|
421
|
-
'doctor', 'physician', 'surgeon', 'nurse', 'therapist',
|
|
422
|
-
'cardiologist', 'oncologist', 'neurologist', 'psychiatrist', 'psychologist',
|
|
423
|
-
'radiologist', 'pathologist', 'anesthesiologist', 'dermatologist',
|
|
424
|
-
'pediatrician', 'obstetrician', 'gynecologist', 'ophthalmologist',
|
|
425
|
-
'dentist', 'orthodontist', 'pharmacist', 'paramedic', 'emt',
|
|
426
|
-
// Roles - Legal
|
|
427
|
-
'lawyer', 'attorney', 'judge', 'paralegal',
|
|
428
|
-
'teacher', 'professor', 'instructor', 'educator', 'tutor',
|
|
429
|
-
'student', 'pupil', 'learner', 'trainee', 'intern',
|
|
430
|
-
'artist', 'musician', 'painter', 'sculptor', 'performer',
|
|
431
|
-
'author', 'writer', 'journalist', 'editor', 'reporter',
|
|
432
|
-
'researcher', 'scientist', 'scholar', 'academic',
|
|
433
|
-
'accountant', 'auditor', 'banker', 'trader', 'broker',
|
|
434
|
-
'salesperson', 'marketer', 'recruiter', 'agent',
|
|
435
|
-
// Social Relationships
|
|
436
|
-
'friend', 'colleague', 'coworker', 'teammate', 'partner',
|
|
437
|
-
'customer', 'client', 'vendor', 'supplier', 'contractor',
|
|
438
|
-
'mentor', 'mentee', 'coach', 'advisor', 'counselor',
|
|
439
|
-
'volunteer', 'activist', 'advocate', 'supporter',
|
|
440
|
-
// Demographics
|
|
441
|
-
'male', 'female', 'adult', 'child', 'teen', 'senior', 'junior'
|
|
442
|
-
], [NounType.Person], 0.9);
|
|
443
|
-
// Organization (70+ keywords)
|
|
444
|
-
add([
|
|
445
|
-
'organization', 'company', 'business', 'corporation', 'enterprise',
|
|
446
|
-
'firm', 'agency', 'bureau', 'office', 'department',
|
|
447
|
-
'startup', 'venture', 'subsidiary', 'branch', 'division',
|
|
448
|
-
'institution', 'foundation', 'association', 'society', 'club',
|
|
449
|
-
'nonprofit', 'ngo', 'charity', 'trust', 'federation',
|
|
450
|
-
'government', 'ministry', 'administration', 'authority',
|
|
451
|
-
'university', 'college', 'school', 'academy', 'institute',
|
|
452
|
-
'hospital', 'clinic', 'medical center', 'healthcare',
|
|
453
|
-
'bank', 'credit union', 'financial', 'insurance',
|
|
454
|
-
'manufacturer', 'factory', 'plant', 'facility',
|
|
455
|
-
'retailer', 'store', 'shop', 'outlet', 'chain',
|
|
456
|
-
'restaurant', 'hotel', 'resort', 'casino',
|
|
457
|
-
'publisher', 'studio', 'gallery', 'museum', 'library',
|
|
458
|
-
'lab', 'laboratory', 'research center',
|
|
459
|
-
'team', 'squad', 'crew', 'group', 'committee'
|
|
460
|
-
], [NounType.Organization], 0.9);
|
|
461
|
-
// Location (60+ keywords)
|
|
462
|
-
add([
|
|
463
|
-
'location', 'place', 'area', 'region', 'zone', 'district',
|
|
464
|
-
'city', 'town', 'village', 'municipality', 'metro',
|
|
465
|
-
'country', 'nation', 'state', 'province', 'territory',
|
|
466
|
-
'county', 'parish', 'prefecture', 'canton',
|
|
467
|
-
'continent', 'island', 'peninsula', 'archipelago',
|
|
468
|
-
'street', 'road', 'avenue', 'boulevard', 'lane', 'drive',
|
|
469
|
-
'address', 'building', 'structure', 'tower', 'complex',
|
|
470
|
-
'office', 'headquarters', 'hq', 'campus', 'site',
|
|
471
|
-
'facility', 'center', 'venue', 'space', 'room',
|
|
472
|
-
'warehouse', 'depot', 'terminal', 'station', 'port',
|
|
473
|
-
'park', 'garden', 'plaza', 'square', 'mall',
|
|
474
|
-
'neighborhood', 'suburb', 'downtown', 'uptown',
|
|
475
|
-
'north', 'south', 'east', 'west', 'central',
|
|
476
|
-
'coastal', 'inland', 'urban', 'rural', 'remote'
|
|
477
|
-
], [NounType.Location], 0.9);
|
|
478
|
-
// Document (80+ keywords)
|
|
479
|
-
add([
|
|
480
|
-
'document', 'file', 'text', 'writing', 'manuscript',
|
|
481
|
-
'report', 'summary', 'brief', 'overview', 'analysis',
|
|
482
|
-
'article', 'essay', 'paper', 'publication', 'journal',
|
|
483
|
-
'book', 'ebook', 'novel', 'chapter', 'volume',
|
|
484
|
-
'manual', 'guide', 'handbook', 'reference', 'documentation',
|
|
485
|
-
'tutorial', 'howto', 'walkthrough', 'instructions',
|
|
486
|
-
'specification', 'spec', 'standard', 'protocol',
|
|
487
|
-
'proposal', 'pitch', 'presentation', 'slide', 'deck',
|
|
488
|
-
'contract', 'agreement', 'license', 'terms', 'policy',
|
|
489
|
-
'invoice', 'receipt', 'statement', 'bill', 'voucher',
|
|
490
|
-
'form', 'application', 'survey', 'questionnaire',
|
|
491
|
-
'transcript', 'minutes', 'record', 'log', 'entry',
|
|
492
|
-
'note', 'memo', 'message', 'email', 'letter',
|
|
493
|
-
'whitepaper', 'thesis', 'dissertation', 'abstract',
|
|
494
|
-
'readme', 'changelog', 'documentation', 'wiki',
|
|
495
|
-
'cv', 'resume', 'portfolio', 'profile'
|
|
496
|
-
], [NounType.Document], 0.9);
|
|
497
|
-
// Media (40+ keywords)
|
|
498
|
-
add([
|
|
499
|
-
'media', 'multimedia', 'content',
|
|
500
|
-
'image', 'photo', 'picture', 'photograph', 'illustration',
|
|
501
|
-
'graphic', 'icon', 'logo', 'banner', 'thumbnail',
|
|
502
|
-
'video', 'movie', 'film', 'clip', 'recording',
|
|
503
|
-
'animation', 'gif', 'webm', 'stream', 'broadcast',
|
|
504
|
-
'audio', 'sound', 'music', 'song', 'track', 'album',
|
|
505
|
-
'podcast', 'episode', 'audiobook', 'voicemail',
|
|
506
|
-
'screenshot', 'screen capture', 'demo', 'tutorial',
|
|
507
|
-
'asset', 'resource', 'attachment'
|
|
508
|
-
], [NounType.Media], 0.85);
|
|
509
|
-
// Concept/Topic (80+ keywords)
|
|
510
|
-
add([
|
|
511
|
-
'concept', 'idea', 'notion', 'theory', 'principle',
|
|
512
|
-
'philosophy', 'ideology', 'belief', 'doctrine',
|
|
513
|
-
'topic', 'subject', 'theme', 'matter', 'issue',
|
|
514
|
-
'category', 'classification', 'taxonomy', 'domain',
|
|
515
|
-
'field', 'discipline', 'specialty', 'area',
|
|
516
|
-
'technology', 'tech', 'innovation', 'invention',
|
|
517
|
-
'science', 'scientific', 'research',
|
|
518
|
-
'mathematics', 'math', 'statistics', 'algebra', 'calculus',
|
|
519
|
-
'physics', 'quantum', 'mechanics', 'thermodynamics',
|
|
520
|
-
'chemistry', 'biology', 'genetics', 'neuroscience',
|
|
521
|
-
'engineering', 'architecture', 'design',
|
|
522
|
-
'computer science', 'programming', 'algorithm',
|
|
523
|
-
'artificial intelligence', 'machine learning', 'ai', 'ml',
|
|
524
|
-
'data science', 'analytics', 'big data',
|
|
525
|
-
'history', 'historical', 'ancient', 'medieval', 'modern',
|
|
526
|
-
'geography', 'geology', 'ecology', 'environment',
|
|
527
|
-
'literature', 'poetry', 'fiction', 'nonfiction',
|
|
528
|
-
'art', 'artistic', 'visual', 'creative',
|
|
529
|
-
'music', 'musical', 'classical', 'jazz', 'rock',
|
|
530
|
-
'sports', 'athletics', 'competition', 'game',
|
|
531
|
-
'politics', 'political', 'government', 'policy',
|
|
532
|
-
'economics', 'economic', 'finance', 'market',
|
|
533
|
-
'psychology', 'sociology', 'anthropology',
|
|
534
|
-
'religion', 'spiritual', 'philosophy'
|
|
535
|
-
], [NounType.Concept], 0.8);
|
|
536
|
-
// Event (50+ keywords)
|
|
537
|
-
add([
|
|
538
|
-
'event', 'occasion', 'happening', 'occurrence',
|
|
539
|
-
'meeting', 'conference', 'summit', 'convention',
|
|
540
|
-
'seminar', 'symposium', 'colloquium', 'forum',
|
|
541
|
-
'workshop', 'training', 'bootcamp', 'course',
|
|
542
|
-
'webinar', 'presentation', 'talk', 'lecture',
|
|
543
|
-
'session', 'class', 'lesson', 'tutorial',
|
|
544
|
-
'party', 'celebration', 'festivity', 'gathering',
|
|
545
|
-
'ceremony', 'ritual', 'service', 'function',
|
|
546
|
-
'festival', 'carnival', 'fair', 'exhibition',
|
|
547
|
-
'concert', 'performance', 'show', 'gig',
|
|
548
|
-
'game', 'match', 'tournament', 'championship',
|
|
549
|
-
'race', 'competition', 'contest', 'trial',
|
|
550
|
-
'launch', 'release', 'premiere', 'debut',
|
|
551
|
-
'announcement', 'reveal', 'unveiling'
|
|
552
|
-
], [NounType.Event], 0.85);
|
|
553
|
-
// Product (50+ keywords)
|
|
554
|
-
add([
|
|
555
|
-
'product', 'item', 'goods', 'merchandise', 'commodity',
|
|
556
|
-
'offering', 'solution', 'package', 'bundle',
|
|
557
|
-
'software', 'app', 'application', 'program', 'tool',
|
|
558
|
-
'platform', 'system', 'framework', 'library',
|
|
559
|
-
'device', 'gadget', 'machine', 'equipment', 'apparatus',
|
|
560
|
-
'hardware', 'component', 'part', 'accessory',
|
|
561
|
-
'vehicle', 'car', 'automobile', 'truck', 'bike',
|
|
562
|
-
'phone', 'smartphone', 'mobile', 'tablet', 'ipad',
|
|
563
|
-
'computer', 'laptop', 'desktop', 'pc', 'mac',
|
|
564
|
-
'watch', 'wearable', 'tracker', 'monitor',
|
|
565
|
-
'camera', 'lens', 'sensor', 'scanner'
|
|
566
|
-
], [NounType.Product], 0.85);
|
|
567
|
-
// Service (40+ keywords)
|
|
568
|
-
add([
|
|
569
|
-
'service', 'offering', 'solution', 'support',
|
|
570
|
-
'consulting', 'advisory', 'guidance', 'assistance',
|
|
571
|
-
'maintenance', 'repair', 'installation', 'setup',
|
|
572
|
-
'hosting', 'cloud', 'saas', 'paas', 'iaas',
|
|
573
|
-
'delivery', 'shipping', 'logistics', 'transport',
|
|
574
|
-
'subscription', 'membership', 'plan', 'tier',
|
|
575
|
-
'training', 'education', 'coaching', 'mentoring',
|
|
576
|
-
'healthcare', 'medical', 'dental', 'therapy',
|
|
577
|
-
'legal', 'accounting', 'financial', 'insurance',
|
|
578
|
-
'marketing', 'advertising', 'promotion', 'pr'
|
|
579
|
-
], [NounType.Service], 0.85);
|
|
580
|
-
// User (30+ keywords)
|
|
581
|
-
add([
|
|
582
|
-
'user', 'account', 'profile', 'identity',
|
|
583
|
-
'username', 'userid', 'login', 'credential',
|
|
584
|
-
'subscriber', 'follower', 'fan', 'supporter',
|
|
585
|
-
'member', 'participant', 'contributor', 'author',
|
|
586
|
-
'viewer', 'reader', 'listener', 'watcher',
|
|
587
|
-
'player', 'gamer', 'competitor', 'contestant',
|
|
588
|
-
'guest', 'visitor', 'attendee', 'participant'
|
|
589
|
-
], [NounType.User], 0.8);
|
|
590
|
-
// Task/Project (60+ keywords)
|
|
591
|
-
add([
|
|
592
|
-
// Tasks
|
|
593
|
-
'task', 'todo', 'action', 'activity', 'job',
|
|
594
|
-
'assignment', 'chore', 'duty', 'work', 'effort',
|
|
595
|
-
'ticket', 'issue', 'bug', 'defect', 'problem',
|
|
596
|
-
'feature', 'enhancement', 'improvement', 'request',
|
|
597
|
-
'story', 'epic', 'saga', 'initiative',
|
|
598
|
-
'backlog', 'queue', 'pipeline', 'workflow',
|
|
599
|
-
// Projects
|
|
600
|
-
'project', 'program', 'initiative', 'undertaking',
|
|
601
|
-
'campaign', 'drive', 'effort', 'venture',
|
|
602
|
-
'plan', 'scheme', 'strategy', 'roadmap',
|
|
603
|
-
'milestone', 'deliverable', 'objective', 'goal',
|
|
604
|
-
'sprint', 'iteration', 'cycle', 'phase',
|
|
605
|
-
'release', 'version', 'build', 'deployment'
|
|
606
|
-
], [NounType.Task], 0.8);
|
|
607
|
-
// Process (30+ keywords)
|
|
608
|
-
add([
|
|
609
|
-
'process', 'procedure', 'method', 'approach',
|
|
610
|
-
'workflow', 'pipeline', 'sequence', 'flow',
|
|
611
|
-
'algorithm', 'logic', 'routine', 'operation',
|
|
612
|
-
'protocol', 'standard', 'guideline', 'practice',
|
|
613
|
-
'step', 'stage', 'phase', 'cycle',
|
|
614
|
-
'system', 'framework', 'structure', 'architecture',
|
|
615
|
-
'automation', 'mechanism', 'procedure'
|
|
616
|
-
], [NounType.Process], 0.75);
|
|
617
|
-
// Collection/Dataset (40+ keywords)
|
|
618
|
-
add([
|
|
619
|
-
'collection', 'set', 'group', 'batch', 'bundle',
|
|
620
|
-
'list', 'array', 'series', 'sequence', 'range',
|
|
621
|
-
'category', 'class', 'type', 'kind', 'sort',
|
|
622
|
-
'dataset', 'data', 'database', 'table', 'schema',
|
|
623
|
-
'corpus', 'repository', 'archive', 'library',
|
|
624
|
-
'catalog', 'index', 'registry', 'directory',
|
|
625
|
-
'inventory', 'stockpile', 'cache', 'pool',
|
|
626
|
-
'queue', 'stack', 'heap', 'tree', 'graph'
|
|
627
|
-
], [NounType.Collection], 0.75);
|
|
628
|
-
// State/Role/Topic (25+ keywords each)
|
|
629
|
-
add([
|
|
630
|
-
'state', 'status', 'condition', 'situation',
|
|
631
|
-
'phase', 'stage', 'level', 'mode',
|
|
632
|
-
'active', 'inactive', 'pending', 'completed',
|
|
633
|
-
'open', 'closed', 'locked', 'enabled', 'disabled'
|
|
634
|
-
], [NounType.State], 0.7);
|
|
635
|
-
add([
|
|
636
|
-
'role', 'position', 'title', 'rank',
|
|
637
|
-
'responsibility', 'duty', 'function', 'capacity',
|
|
638
|
-
'permission', 'access', 'privilege', 'right'
|
|
639
|
-
], [NounType.Role], 0.7);
|
|
640
|
-
add([
|
|
641
|
-
'topic', 'subject', 'theme', 'matter',
|
|
642
|
-
'area', 'field', 'domain', 'sector',
|
|
643
|
-
'category', 'genre', 'type', 'style'
|
|
644
|
-
], [NounType.Topic], 0.7);
|
|
645
|
-
// Scientific Types
|
|
646
|
-
add([
|
|
647
|
-
'hypothesis', 'theory', 'conjecture', 'proposition',
|
|
648
|
-
'assumption', 'premise', 'postulate', 'thesis'
|
|
649
|
-
], [NounType.Hypothesis], 0.8);
|
|
650
|
-
add([
|
|
651
|
-
'experiment', 'study', 'trial', 'test',
|
|
652
|
-
'research', 'investigation', 'analysis', 'examination'
|
|
653
|
-
], [NounType.Experiment], 0.8);
|
|
654
|
-
// Legal Types
|
|
655
|
-
add([
|
|
656
|
-
'contract', 'agreement', 'treaty', 'pact',
|
|
657
|
-
'deal', 'arrangement', 'settlement', 'accord'
|
|
658
|
-
], [NounType.Contract], 0.85);
|
|
659
|
-
add([
|
|
660
|
-
'regulation', 'rule', 'law', 'statute',
|
|
661
|
-
'ordinance', 'code', 'compliance', 'requirement'
|
|
662
|
-
], [NounType.Regulation], 0.85);
|
|
663
|
-
// Technical Types
|
|
664
|
-
add([
|
|
665
|
-
'interface', 'api', 'endpoint', 'protocol',
|
|
666
|
-
'contract', 'specification', 'definition'
|
|
667
|
-
], [NounType.Interface], 0.8);
|
|
668
|
-
add([
|
|
669
|
-
'resource', 'asset', 'capacity', 'bandwidth',
|
|
670
|
-
'storage', 'memory', 'compute', 'infrastructure'
|
|
671
|
-
], [NounType.Resource], 0.75);
|
|
672
|
-
return map;
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* Build phrase dictionary for multi-word matching
|
|
676
|
-
*/
|
|
677
|
-
buildPhraseMap() {
|
|
678
|
-
const map = new Map();
|
|
679
|
-
// Helper to add phrases
|
|
680
|
-
const add = (phrases, types, confidence) => {
|
|
681
|
-
for (const phrase of phrases) {
|
|
682
|
-
map.set(phrase, { types, confidence });
|
|
683
|
-
}
|
|
684
|
-
};
|
|
685
|
-
// Person-related phrases
|
|
686
|
-
add([
|
|
687
|
-
'software engineer', 'software developer', 'web developer',
|
|
688
|
-
'data scientist', 'machine learning engineer', 'ml engineer',
|
|
689
|
-
'product manager', 'project manager', 'engineering manager',
|
|
690
|
-
'ux designer', 'ui designer', 'graphic designer',
|
|
691
|
-
'sales rep', 'account manager', 'customer success'
|
|
692
|
-
], [NounType.Person], 0.95);
|
|
693
|
-
// Location phrases
|
|
694
|
-
add([
|
|
695
|
-
'san francisco', 'new york', 'los angeles', 'silicon valley',
|
|
696
|
-
'bay area', 'new york city', 'washington dc',
|
|
697
|
-
'hong kong', 'united states', 'united kingdom'
|
|
698
|
-
], [NounType.Location], 0.95);
|
|
699
|
-
// Concept phrases
|
|
700
|
-
add([
|
|
701
|
-
'artificial intelligence', 'machine learning', 'deep learning',
|
|
702
|
-
'natural language processing', 'computer vision',
|
|
703
|
-
'quantum computing', 'quantum mechanics', 'quantum physics',
|
|
704
|
-
'climate change', 'global warming', 'renewable energy',
|
|
705
|
-
'data science', 'big data', 'data analytics'
|
|
706
|
-
], [NounType.Concept], 0.95);
|
|
707
|
-
// Multi-type phrases (query patterns)
|
|
708
|
-
add([
|
|
709
|
-
'people at', 'employees at', 'workers at', 'staff at',
|
|
710
|
-
'team at', 'people from', 'employees from'
|
|
711
|
-
], [NounType.Person, NounType.Organization], 0.9);
|
|
712
|
-
add([
|
|
713
|
-
'companies in', 'organizations in', 'businesses in',
|
|
714
|
-
'offices in', 'locations in'
|
|
715
|
-
], [NounType.Organization, NounType.Location], 0.9);
|
|
716
|
-
add([
|
|
717
|
-
'documents about', 'papers about', 'articles about',
|
|
718
|
-
'reports about', 'research about'
|
|
719
|
-
], [NounType.Document, NounType.Concept], 0.9);
|
|
720
|
-
add([
|
|
721
|
-
'events in', 'conferences in', 'meetings in',
|
|
722
|
-
'workshops in', 'seminars in'
|
|
723
|
-
], [NounType.Event, NounType.Location], 0.9);
|
|
724
|
-
add([
|
|
725
|
-
'products from', 'services from', 'offerings from',
|
|
726
|
-
'solutions from'
|
|
727
|
-
], [NounType.Product, NounType.Organization], 0.85);
|
|
728
|
-
return map;
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* Get statistics about the inference system
|
|
732
|
-
*/
|
|
733
|
-
getStats() {
|
|
734
|
-
return {
|
|
735
|
-
keywordCount: this.keywordMap.size,
|
|
736
|
-
phraseCount: this.phraseMap.size,
|
|
737
|
-
config: this.config
|
|
738
|
-
};
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
/**
|
|
742
|
-
* Global singleton instance for convenience
|
|
743
|
-
*/
|
|
744
|
-
let globalInstance = null;
|
|
745
|
-
/**
|
|
746
|
-
* Get or create the global TypeInferenceSystem instance
|
|
747
|
-
*/
|
|
748
|
-
export function getTypeInferenceSystem(config) {
|
|
749
|
-
if (!globalInstance) {
|
|
750
|
-
globalInstance = new TypeInferenceSystem(config);
|
|
751
|
-
}
|
|
752
|
-
return globalInstance;
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Convenience function to infer types from a query
|
|
756
|
-
*/
|
|
757
|
-
export function inferTypes(query, config) {
|
|
758
|
-
return getTypeInferenceSystem(config).inferTypes(query);
|
|
759
|
-
}
|
|
760
|
-
//# sourceMappingURL=typeInference.js.map
|