@soulcraft/brainy 2.0.2 → 2.3.0

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/README.md +2 -2
  2. package/dist/augmentations/AugmentationMetadataContract.d.ts +94 -0
  3. package/dist/augmentations/AugmentationMetadataContract.js +306 -0
  4. package/dist/augmentations/apiServerAugmentation.d.ts +1 -0
  5. package/dist/augmentations/apiServerAugmentation.js +1 -0
  6. package/dist/augmentations/batchProcessingAugmentation.d.ts +1 -0
  7. package/dist/augmentations/batchProcessingAugmentation.js +1 -0
  8. package/dist/augmentations/brainyAugmentation.d.ts +16 -0
  9. package/dist/augmentations/cacheAugmentation.d.ts +1 -0
  10. package/dist/augmentations/cacheAugmentation.js +1 -0
  11. package/dist/augmentations/conduitAugmentations.d.ts +1 -0
  12. package/dist/augmentations/conduitAugmentations.js +1 -0
  13. package/dist/augmentations/connectionPoolAugmentation.d.ts +1 -0
  14. package/dist/augmentations/connectionPoolAugmentation.js +1 -0
  15. package/dist/augmentations/entityRegistryAugmentation.d.ts +2 -0
  16. package/dist/augmentations/entityRegistryAugmentation.js +2 -0
  17. package/dist/augmentations/indexAugmentation.d.ts +1 -0
  18. package/dist/augmentations/indexAugmentation.js +1 -0
  19. package/dist/augmentations/intelligentVerbScoringAugmentation.d.ts +4 -0
  20. package/dist/augmentations/intelligentVerbScoringAugmentation.js +4 -0
  21. package/dist/augmentations/metadataEnforcer.d.ts +20 -0
  22. package/dist/augmentations/metadataEnforcer.js +171 -0
  23. package/dist/augmentations/metricsAugmentation.d.ts +2 -7
  24. package/dist/augmentations/metricsAugmentation.js +1 -0
  25. package/dist/augmentations/monitoringAugmentation.d.ts +1 -0
  26. package/dist/augmentations/monitoringAugmentation.js +1 -0
  27. package/dist/augmentations/neuralImport.d.ts +16 -3
  28. package/dist/augmentations/neuralImport.js +199 -55
  29. package/dist/augmentations/requestDeduplicatorAugmentation.d.ts +1 -0
  30. package/dist/augmentations/requestDeduplicatorAugmentation.js +1 -0
  31. package/dist/augmentations/serverSearchAugmentations.d.ts +2 -0
  32. package/dist/augmentations/serverSearchAugmentations.js +2 -0
  33. package/dist/augmentations/storageAugmentation.d.ts +1 -0
  34. package/dist/augmentations/storageAugmentation.js +1 -0
  35. package/dist/augmentations/synapseAugmentation.d.ts +4 -0
  36. package/dist/augmentations/synapseAugmentation.js +4 -0
  37. package/dist/augmentations/typeMatching/intelligentTypeMatcher.d.ts +83 -0
  38. package/dist/augmentations/typeMatching/intelligentTypeMatcher.js +425 -0
  39. package/dist/augmentations/walAugmentation.d.ts +1 -0
  40. package/dist/augmentations/walAugmentation.js +1 -0
  41. package/dist/brainyData.d.ts +32 -5
  42. package/dist/brainyData.js +263 -111
  43. package/dist/importManager.d.ts +78 -0
  44. package/dist/importManager.js +258 -0
  45. package/dist/neural/embeddedPatterns.d.ts +1 -1
  46. package/dist/neural/embeddedPatterns.js +1 -1
  47. package/dist/triple/TripleIntelligence.d.ts +4 -0
  48. package/dist/triple/TripleIntelligence.js +39 -9
  49. package/dist/utils/deletedItemsIndex.d.ts +59 -0
  50. package/dist/utils/deletedItemsIndex.js +98 -0
  51. package/dist/utils/ensureDeleted.d.ts +38 -0
  52. package/dist/utils/ensureDeleted.js +79 -0
  53. package/dist/utils/metadataFilter.js +5 -0
  54. package/dist/utils/metadataIndex.d.ts +4 -0
  55. package/dist/utils/metadataIndex.js +45 -0
  56. package/dist/utils/metadataNamespace.d.ts +113 -0
  57. package/dist/utils/metadataNamespace.js +162 -0
  58. package/dist/utils/periodicCleanup.d.ts +87 -0
  59. package/dist/utils/periodicCleanup.js +219 -0
  60. package/package.json +13 -5
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Runtime enforcement of metadata contracts
3
+ * Ensures augmentations only access declared fields
4
+ */
5
+ export class MetadataEnforcer {
6
+ /**
7
+ * Enforce metadata access based on augmentation contract
8
+ * Returns a wrapped metadata object that enforces the contract
9
+ */
10
+ static enforce(augmentation, metadata, operation = 'write') {
11
+ // Handle simple contracts
12
+ if (augmentation.metadata === 'none') {
13
+ // No access at all
14
+ if (operation === 'read')
15
+ return null;
16
+ throw new Error(`Augmentation '${augmentation.name}' has metadata='none' - cannot access metadata`);
17
+ }
18
+ if (augmentation.metadata === 'readonly') {
19
+ if (operation === 'read') {
20
+ // Return frozen deep clone for read-only access
21
+ return deepFreeze(deepClone(metadata));
22
+ }
23
+ throw new Error(`Augmentation '${augmentation.name}' has metadata='readonly' - cannot write`);
24
+ }
25
+ // Handle specific field access
26
+ const access = augmentation.metadata;
27
+ if (operation === 'read') {
28
+ // For reads, filter to allowed fields
29
+ if (access.reads === '*') {
30
+ return deepClone(metadata); // Can read everything
31
+ }
32
+ if (!access.reads) {
33
+ return {}; // No read access
34
+ }
35
+ // Filter to specific fields
36
+ const filtered = {};
37
+ for (const field of access.reads) {
38
+ if (field.includes('.')) {
39
+ // Handle nested fields like '_brainy.deleted'
40
+ const parts = field.split('.');
41
+ let source = metadata;
42
+ let target = filtered;
43
+ for (let i = 0; i < parts.length - 1; i++) {
44
+ const part = parts[i];
45
+ if (!source[part])
46
+ break;
47
+ if (!target[part])
48
+ target[part] = {};
49
+ source = source[part];
50
+ target = target[part];
51
+ }
52
+ const lastPart = parts[parts.length - 1];
53
+ if (source && lastPart in source) {
54
+ target[lastPart] = source[lastPart];
55
+ }
56
+ }
57
+ else {
58
+ // Simple field
59
+ if (field in metadata) {
60
+ filtered[field] = metadata[field];
61
+ }
62
+ }
63
+ }
64
+ return filtered;
65
+ }
66
+ // For writes, create a proxy that validates
67
+ return new Proxy(metadata, {
68
+ set(target, prop, value) {
69
+ const field = String(prop);
70
+ // Check if write is allowed
71
+ if (access.writes === '*') {
72
+ // Can write anything
73
+ target[prop] = value;
74
+ return true;
75
+ }
76
+ if (!access.writes || !access.writes.includes(field)) {
77
+ throw new Error(`Augmentation '${augmentation.name}' cannot write to field '${field}'. ` +
78
+ `Allowed writes: ${access.writes?.join(', ') || 'none'}`);
79
+ }
80
+ // Check namespace if specified
81
+ if (access.namespace && !field.startsWith(access.namespace)) {
82
+ console.warn(`Augmentation '${augmentation.name}' writing outside its namespace. ` +
83
+ `Expected: ${access.namespace}.*, got: ${field}`);
84
+ }
85
+ target[prop] = value;
86
+ return true;
87
+ },
88
+ deleteProperty(target, prop) {
89
+ const field = String(prop);
90
+ // Deletion counts as a write
91
+ if (access.writes === '*' || access.writes?.includes(field)) {
92
+ delete target[prop];
93
+ return true;
94
+ }
95
+ throw new Error(`Augmentation '${augmentation.name}' cannot delete field '${field}'`);
96
+ }
97
+ });
98
+ }
99
+ /**
100
+ * Validate that an augmentation's actual behavior matches its contract
101
+ * Used in testing to verify contracts are accurate
102
+ */
103
+ static async validateContract(augmentation, testMetadata = { test: 'data', _brainy: { deleted: false } }) {
104
+ const violations = [];
105
+ // Test read access
106
+ try {
107
+ const readable = this.enforce(augmentation, testMetadata, 'read');
108
+ if (augmentation.metadata === 'none' && readable !== null) {
109
+ violations.push(`Contract says 'none' but got readable metadata`);
110
+ }
111
+ }
112
+ catch (error) {
113
+ violations.push(`Read enforcement error: ${error}`);
114
+ }
115
+ // Test write access
116
+ try {
117
+ const writable = this.enforce(augmentation, testMetadata, 'write');
118
+ if (augmentation.metadata === 'none') {
119
+ violations.push(`Contract says 'none' but got writable metadata`);
120
+ }
121
+ if (augmentation.metadata === 'readonly') {
122
+ // Try to write - should fail
123
+ try {
124
+ writable.testWrite = 'value';
125
+ violations.push(`Contract says 'readonly' but write succeeded`);
126
+ }
127
+ catch {
128
+ // Expected to fail
129
+ }
130
+ }
131
+ }
132
+ catch (error) {
133
+ // Expected for 'none' and 'readonly' on write
134
+ if (augmentation.metadata !== 'none' && augmentation.metadata !== 'readonly') {
135
+ violations.push(`Write enforcement error: ${error}`);
136
+ }
137
+ }
138
+ return {
139
+ valid: violations.length === 0,
140
+ violations
141
+ };
142
+ }
143
+ }
144
+ // Helper functions
145
+ function deepClone(obj) {
146
+ if (obj === null || typeof obj !== 'object')
147
+ return obj;
148
+ if (obj instanceof Date)
149
+ return new Date(obj);
150
+ if (obj instanceof Array)
151
+ return obj.map(item => deepClone(item));
152
+ const cloned = {};
153
+ for (const key in obj) {
154
+ if (obj.hasOwnProperty(key)) {
155
+ cloned[key] = deepClone(obj[key]);
156
+ }
157
+ }
158
+ return cloned;
159
+ }
160
+ function deepFreeze(obj) {
161
+ Object.freeze(obj);
162
+ Object.getOwnPropertyNames(obj).forEach(prop => {
163
+ if (obj[prop] !== null &&
164
+ (typeof obj[prop] === 'object' || typeof obj[prop] === 'function') &&
165
+ !Object.isFrozen(obj[prop])) {
166
+ deepFreeze(obj[prop]);
167
+ }
168
+ });
169
+ return obj;
170
+ }
171
+ //# sourceMappingURL=metadataEnforcer.js.map
@@ -27,6 +27,7 @@ export interface MetricsConfig {
27
27
  * - Zero-config with smart defaults
28
28
  */
29
29
  export declare class MetricsAugmentation extends BaseAugmentation {
30
+ readonly metadata: "readonly";
30
31
  readonly name = "metrics";
31
32
  readonly timing: "after";
32
33
  operations: ("add" | "search" | "delete" | "clear" | "all")[];
@@ -126,13 +127,7 @@ export declare class MetricsAugmentation extends BaseAugmentation {
126
127
  averageSearchTimeMs: number;
127
128
  searchesLastHour: number;
128
129
  searchesLastDay: number;
129
- topSearchTerms
130
- /**
131
- * Update storage size metrics
132
- */
133
- ? /**
134
- * Update storage size metrics
135
- */: string[];
130
+ topSearchTerms?: string[];
136
131
  } | undefined;
137
132
  verbStatistics?: {
138
133
  totalVerbs: number;
@@ -21,6 +21,7 @@ import { StatisticsCollector } from '../utils/statisticsCollector.js';
21
21
  export class MetricsAugmentation extends BaseAugmentation {
22
22
  constructor(config = {}) {
23
23
  super();
24
+ this.metadata = 'readonly'; // Reads metadata for metrics
24
25
  this.name = 'metrics';
25
26
  this.timing = 'after';
26
27
  this.operations = ['add', 'search', 'delete', 'clear', 'all'];
@@ -28,6 +28,7 @@ export interface MonitoringConfig {
28
28
  * - Zero-config with smart defaults
29
29
  */
30
30
  export declare class MonitoringAugmentation extends BaseAugmentation {
31
+ readonly metadata: "readonly";
31
32
  readonly name = "monitoring";
32
33
  readonly timing: "after";
33
34
  operations: ("search" | "add" | "delete" | "all")[];
@@ -23,6 +23,7 @@ import { DistributedConfigManager as ConfigManager } from '../distributed/config
23
23
  export class MonitoringAugmentation extends BaseAugmentation {
24
24
  constructor(config = {}) {
25
25
  super();
26
+ this.metadata = 'readonly'; // Reads metadata for monitoring
26
27
  this.name = 'monitoring';
27
28
  this.timing = 'after';
28
29
  this.operations = ['search', 'add', 'delete', 'all'];
@@ -55,10 +55,15 @@ export interface NeuralImportConfig {
55
55
  export declare class NeuralImportAugmentation extends BaseAugmentation {
56
56
  readonly name = "neural-import";
57
57
  readonly timing: "before";
58
+ readonly metadata: {
59
+ reads: "*";
60
+ writes: string[];
61
+ };
58
62
  operations: ("add" | "addNoun" | "addVerb" | "all")[];
59
63
  readonly priority = 80;
60
64
  private config;
61
65
  private analysisCache;
66
+ private typeMatcher;
62
67
  constructor(config?: Partial<NeuralImportConfig>);
63
68
  protected onInitialize(): Promise<void>;
64
69
  protected onShutdown(): Promise<void>;
@@ -79,15 +84,23 @@ export declare class NeuralImportAugmentation extends BaseAugmentation {
79
84
  */
80
85
  private parseRawData;
81
86
  /**
82
- * Parse CSV data
87
+ * Parse CSV data - handles quoted values, escaped quotes, and edge cases
83
88
  */
84
89
  private parseCSV;
90
+ /**
91
+ * Parse YAML data
92
+ */
93
+ private parseYAML;
94
+ /**
95
+ * Parse a YAML value (handle strings, numbers, booleans, null)
96
+ */
97
+ private parseYAMLValue;
85
98
  /**
86
99
  * Perform neural analysis on parsed data
87
100
  */
88
101
  private performNeuralAnalysis;
89
102
  /**
90
- * Infer noun type from object structure
103
+ * Infer noun type from object structure using intelligent type matching
91
104
  */
92
105
  private inferNounType;
93
106
  /**
@@ -95,7 +108,7 @@ export declare class NeuralImportAugmentation extends BaseAugmentation {
95
108
  */
96
109
  private detectRelationships;
97
110
  /**
98
- * Infer verb type from field name
111
+ * Infer verb type from field name using intelligent type matching
99
112
  */
100
113
  private inferVerbType;
101
114
  /**
@@ -8,6 +8,8 @@
8
8
  */
9
9
  import { BaseAugmentation } from './brainyAugmentation.js';
10
10
  import * as path from '../universal/path.js';
11
+ import { getTypeMatcher } from './typeMatching/intelligentTypeMatcher.js';
12
+ import { prodLog } from '../utils/logger.js';
11
13
  /**
12
14
  * Neural Import Augmentation - Unified Implementation
13
15
  * Processes data with AI before storage operations
@@ -17,9 +19,14 @@ export class NeuralImportAugmentation extends BaseAugmentation {
17
19
  super();
18
20
  this.name = 'neural-import';
19
21
  this.timing = 'before'; // Process data before storage
22
+ this.metadata = {
23
+ reads: '*', // Needs to read data for analysis
24
+ writes: ['_neuralProcessed', '_neuralConfidence', '_detectedEntities', '_detectedRelationships', '_neuralInsights', 'nounType', 'verbType']
25
+ }; // Enriches metadata with neural analysis
20
26
  this.operations = ['add', 'addNoun', 'addVerb', 'all']; // Use 'all' to catch batch operations
21
27
  this.priority = 80; // High priority for data processing
22
28
  this.analysisCache = new Map();
29
+ this.typeMatcher = null;
23
30
  this.config = {
24
31
  confidenceThreshold: 0.7,
25
32
  enableWeights: true,
@@ -29,7 +36,13 @@ export class NeuralImportAugmentation extends BaseAugmentation {
29
36
  };
30
37
  }
31
38
  async onInitialize() {
32
- this.log('🧠 Neural Import augmentation initialized');
39
+ try {
40
+ this.typeMatcher = await getTypeMatcher();
41
+ this.log('🧠 Neural Import augmentation initialized with intelligent type matching');
42
+ }
43
+ catch (error) {
44
+ this.log('⚠️ Failed to initialize type matcher, falling back to heuristics', 'warn');
45
+ }
33
46
  }
34
47
  async onShutdown() {
35
48
  this.analysisCache.clear();
@@ -128,13 +141,7 @@ export class NeuralImportAugmentation extends BaseAugmentation {
128
141
  return this.parseCSV(content);
129
142
  case 'yaml':
130
143
  case 'yml':
131
- // For now, basic YAML support - in full implementation would use yaml parser
132
- try {
133
- return JSON.parse(content); // Placeholder
134
- }
135
- catch {
136
- return [{ text: content }];
137
- }
144
+ return this.parseYAML(content);
138
145
  case 'txt':
139
146
  case 'text':
140
147
  // Split text into sentences/paragraphs for analysis
@@ -145,24 +152,174 @@ export class NeuralImportAugmentation extends BaseAugmentation {
145
152
  }
146
153
  }
147
154
  /**
148
- * Parse CSV data
155
+ * Parse CSV data - handles quoted values, escaped quotes, and edge cases
149
156
  */
150
157
  parseCSV(content) {
151
- const lines = content.split('\n').filter(line => line.trim());
158
+ const lines = content.split('\n');
152
159
  if (lines.length === 0)
153
160
  return [];
154
- const headers = lines[0].split(',').map(h => h.trim());
161
+ // Parse a CSV line handling quotes
162
+ const parseLine = (line) => {
163
+ const result = [];
164
+ let current = '';
165
+ let inQuotes = false;
166
+ let i = 0;
167
+ while (i < line.length) {
168
+ const char = line[i];
169
+ const nextChar = line[i + 1];
170
+ if (char === '"') {
171
+ if (inQuotes && nextChar === '"') {
172
+ // Escaped quote
173
+ current += '"';
174
+ i += 2;
175
+ }
176
+ else {
177
+ // Toggle quote mode
178
+ inQuotes = !inQuotes;
179
+ i++;
180
+ }
181
+ }
182
+ else if (char === ',' && !inQuotes) {
183
+ // Field separator
184
+ result.push(current.trim());
185
+ current = '';
186
+ i++;
187
+ }
188
+ else {
189
+ current += char;
190
+ i++;
191
+ }
192
+ }
193
+ // Add last field
194
+ result.push(current.trim());
195
+ return result;
196
+ };
197
+ // Parse headers
198
+ const headers = parseLine(lines[0]);
155
199
  const data = [];
200
+ // Parse data rows
156
201
  for (let i = 1; i < lines.length; i++) {
157
- const values = lines[i].split(',').map(v => v.trim());
202
+ const line = lines[i].trim();
203
+ if (!line)
204
+ continue; // Skip empty lines
205
+ const values = parseLine(line);
158
206
  const row = {};
159
207
  headers.forEach((header, index) => {
160
- row[header] = values[index] || '';
208
+ const value = values[index] || '';
209
+ // Try to parse numbers
210
+ const num = Number(value);
211
+ row[header] = !isNaN(num) && value !== '' ? num : value;
161
212
  });
162
213
  data.push(row);
163
214
  }
164
215
  return data;
165
216
  }
217
+ /**
218
+ * Parse YAML data
219
+ */
220
+ parseYAML(content) {
221
+ try {
222
+ // Simple YAML parser for basic structures
223
+ // For full YAML support, we'd use js-yaml library
224
+ const lines = content.split('\n');
225
+ const result = [];
226
+ let currentObject = null;
227
+ let currentIndent = 0;
228
+ for (const line of lines) {
229
+ const trimmed = line.trim();
230
+ if (!trimmed || trimmed.startsWith('#'))
231
+ continue; // Skip empty lines and comments
232
+ // Calculate indentation
233
+ const indent = line.length - line.trimStart().length;
234
+ // Check for array item
235
+ if (trimmed.startsWith('- ')) {
236
+ const value = trimmed.substring(2).trim();
237
+ if (indent === 0) {
238
+ // Top-level array item
239
+ if (value.includes(':')) {
240
+ // Object in array
241
+ currentObject = {};
242
+ result.push(currentObject);
243
+ const [key, val] = value.split(':').map(s => s.trim());
244
+ currentObject[key] = this.parseYAMLValue(val);
245
+ }
246
+ else {
247
+ result.push(this.parseYAMLValue(value));
248
+ }
249
+ }
250
+ else if (currentObject) {
251
+ // Nested array
252
+ const lastKey = Object.keys(currentObject).pop();
253
+ if (lastKey) {
254
+ if (!Array.isArray(currentObject[lastKey])) {
255
+ currentObject[lastKey] = [];
256
+ }
257
+ currentObject[lastKey].push(this.parseYAMLValue(value));
258
+ }
259
+ }
260
+ }
261
+ else if (trimmed.includes(':')) {
262
+ // Key-value pair
263
+ const colonIndex = trimmed.indexOf(':');
264
+ const key = trimmed.substring(0, colonIndex).trim();
265
+ const value = trimmed.substring(colonIndex + 1).trim();
266
+ if (indent === 0) {
267
+ // Top-level object
268
+ if (!currentObject) {
269
+ currentObject = {};
270
+ result.push(currentObject);
271
+ }
272
+ currentObject[key] = this.parseYAMLValue(value);
273
+ currentIndent = 0;
274
+ }
275
+ else if (currentObject) {
276
+ // Nested object
277
+ if (indent > currentIndent && !value) {
278
+ // Start of nested object
279
+ const lastKey = Object.keys(currentObject).pop();
280
+ if (lastKey) {
281
+ currentObject[lastKey] = { [key]: '' };
282
+ }
283
+ }
284
+ else {
285
+ currentObject[key] = this.parseYAMLValue(value);
286
+ }
287
+ currentIndent = indent;
288
+ }
289
+ }
290
+ }
291
+ // If we built a single object and not an array, wrap it
292
+ if (result.length === 0 && currentObject) {
293
+ result.push(currentObject);
294
+ }
295
+ return result.length > 0 ? result : [{ text: content }];
296
+ }
297
+ catch (error) {
298
+ prodLog.warn('YAML parsing failed, treating as text:', error);
299
+ return [{ text: content }];
300
+ }
301
+ }
302
+ /**
303
+ * Parse a YAML value (handle strings, numbers, booleans, null)
304
+ */
305
+ parseYAMLValue(value) {
306
+ if (!value || value === '~' || value === 'null')
307
+ return null;
308
+ if (value === 'true')
309
+ return true;
310
+ if (value === 'false')
311
+ return false;
312
+ // Remove quotes if present
313
+ if ((value.startsWith('"') && value.endsWith('"')) ||
314
+ (value.startsWith("'") && value.endsWith("'"))) {
315
+ return value.slice(1, -1);
316
+ }
317
+ // Try to parse as number
318
+ const num = Number(value);
319
+ if (!isNaN(num) && value !== '')
320
+ return num;
321
+ return value;
322
+ }
166
323
  /**
167
324
  * Perform neural analysis on parsed data
168
325
  */
@@ -177,14 +334,14 @@ export class NeuralImportAugmentation extends BaseAugmentation {
177
334
  const entityId = item.id || item.name || item.title || `entity_${Date.now()}_${Math.random()}`;
178
335
  detectedEntities.push({
179
336
  originalData: item,
180
- nounType: this.inferNounType(item),
337
+ nounType: await this.inferNounType(item),
181
338
  confidence: 0.85,
182
339
  suggestedId: String(entityId),
183
340
  reasoning: 'Detected from structured data',
184
341
  alternativeTypes: []
185
342
  });
186
343
  // Detect relationships from references
187
- this.detectRelationships(item, entityId, detectedRelationships);
344
+ await this.detectRelationships(item, entityId, detectedRelationships);
188
345
  }
189
346
  }
190
347
  // Generate insights
@@ -216,36 +373,31 @@ export class NeuralImportAugmentation extends BaseAugmentation {
216
373
  };
217
374
  }
218
375
  /**
219
- * Infer noun type from object structure
376
+ * Infer noun type from object structure using intelligent type matching
220
377
  */
221
- inferNounType(obj) {
222
- // Simple heuristics for type detection
223
- if (obj.email || obj.username)
224
- return 'Person';
225
- if (obj.title && obj.content)
226
- return 'Document';
227
- if (obj.price || obj.product)
228
- return 'Product';
229
- if (obj.date || obj.timestamp)
230
- return 'Event';
231
- if (obj.url || obj.link)
232
- return 'Resource';
233
- if (obj.lat || obj.longitude)
234
- return 'Location';
235
- // Default fallback
236
- return 'Entity';
378
+ async inferNounType(obj) {
379
+ if (!this.typeMatcher) {
380
+ // Initialize type matcher if not available
381
+ this.typeMatcher = await getTypeMatcher();
382
+ }
383
+ const result = await this.typeMatcher.matchNounType(obj);
384
+ // Log if confidence is low for debugging
385
+ if (result.confidence < 0.5) {
386
+ this.log(`Low confidence (${result.confidence.toFixed(2)}) for noun type: ${result.type}`, 'warn');
387
+ }
388
+ return result.type;
237
389
  }
238
390
  /**
239
391
  * Detect relationships from object references
240
392
  */
241
- detectRelationships(obj, sourceId, relationships) {
393
+ async detectRelationships(obj, sourceId, relationships) {
242
394
  // Look for reference patterns
243
395
  for (const [key, value] of Object.entries(obj)) {
244
396
  if (key.endsWith('Id') || key.endsWith('_id') || key === 'parentId' || key === 'userId') {
245
397
  relationships.push({
246
398
  sourceId,
247
399
  targetId: String(value),
248
- verbType: this.inferVerbType(key),
400
+ verbType: await this.inferVerbType(key, obj, { id: value }),
249
401
  confidence: 0.75,
250
402
  weight: 1,
251
403
  reasoning: `Reference detected in field: ${key}`,
@@ -259,7 +411,7 @@ export class NeuralImportAugmentation extends BaseAugmentation {
259
411
  relationships.push({
260
412
  sourceId,
261
413
  targetId: String(targetId),
262
- verbType: this.inferVerbType(key),
414
+ verbType: await this.inferVerbType(key, obj, { id: targetId }),
263
415
  confidence: 0.7,
264
416
  weight: 1,
265
417
  reasoning: `Array reference in field: ${key}`,
@@ -271,27 +423,19 @@ export class NeuralImportAugmentation extends BaseAugmentation {
271
423
  }
272
424
  }
273
425
  /**
274
- * Infer verb type from field name
426
+ * Infer verb type from field name using intelligent type matching
275
427
  */
276
- inferVerbType(fieldName) {
277
- const normalized = fieldName.toLowerCase();
278
- if (normalized.includes('parent'))
279
- return 'childOf';
280
- if (normalized.includes('user'))
281
- return 'belongsTo';
282
- if (normalized.includes('author'))
283
- return 'authoredBy';
284
- if (normalized.includes('owner'))
285
- return 'ownedBy';
286
- if (normalized.includes('creator'))
287
- return 'createdBy';
288
- if (normalized.includes('member'))
289
- return 'memberOf';
290
- if (normalized.includes('tag'))
291
- return 'taggedWith';
292
- if (normalized.includes('category'))
293
- return 'categorizedAs';
294
- return 'relatedTo';
428
+ async inferVerbType(fieldName, sourceObj, targetObj) {
429
+ if (!this.typeMatcher) {
430
+ // Initialize type matcher if not available
431
+ this.typeMatcher = await getTypeMatcher();
432
+ }
433
+ const result = await this.typeMatcher.matchVerbType(sourceObj, targetObj, fieldName);
434
+ // Log if confidence is low for debugging
435
+ if (result.confidence < 0.5) {
436
+ this.log(`Low confidence (${result.confidence.toFixed(2)}) for verb type: ${result.type}`, 'warn');
437
+ }
438
+ return result.type;
295
439
  }
296
440
  /**
297
441
  * Group entities by type
@@ -13,6 +13,7 @@ interface DeduplicatorConfig {
13
13
  export declare class RequestDeduplicatorAugmentation extends BaseAugmentation {
14
14
  name: string;
15
15
  timing: "around";
16
+ metadata: "none";
16
17
  operations: ("search" | "searchText" | "searchByNounTypes" | "findSimilar" | "get")[];
17
18
  priority: number;
18
19
  private pendingRequests;
@@ -10,6 +10,7 @@ export class RequestDeduplicatorAugmentation extends BaseAugmentation {
10
10
  super();
11
11
  this.name = 'RequestDeduplicator';
12
12
  this.timing = 'around';
13
+ this.metadata = 'none'; // Doesn't access metadata
13
14
  this.operations = ['search', 'searchText', 'searchByNounTypes', 'findSimilar', 'get'];
14
15
  this.priority = 50; // Performance optimization
15
16
  this.pendingRequests = new Map();
@@ -16,6 +16,7 @@ import { BrainyDataInterface } from '../types/brainyDataInterface.js';
16
16
  export declare class ServerSearchConduitAugmentation extends BaseAugmentation {
17
17
  readonly name = "server-search-conduit";
18
18
  readonly timing: "after";
19
+ readonly metadata: "readonly";
19
20
  operations: ("addNoun" | "delete" | "addVerb")[];
20
21
  readonly priority = 20;
21
22
  private localDb;
@@ -101,6 +102,7 @@ export declare class ServerSearchConduitAugmentation extends BaseAugmentation {
101
102
  export declare class ServerSearchActivationAugmentation extends BaseAugmentation {
102
103
  readonly name = "server-search-activation";
103
104
  readonly timing: "after";
105
+ readonly metadata: "readonly";
104
106
  operations: ("search" | "addNoun")[];
105
107
  readonly priority = 20;
106
108
  private conduitAugmentation;
@@ -16,6 +16,7 @@ export class ServerSearchConduitAugmentation extends BaseAugmentation {
16
16
  super();
17
17
  this.name = 'server-search-conduit';
18
18
  this.timing = 'after';
19
+ this.metadata = 'readonly'; // Reads metadata to sync with server
19
20
  this.operations = ['addNoun', 'delete', 'addVerb'];
20
21
  this.priority = 20;
21
22
  this.localDb = null;
@@ -310,6 +311,7 @@ export class ServerSearchActivationAugmentation extends BaseAugmentation {
310
311
  super();
311
312
  this.name = 'server-search-activation';
312
313
  this.timing = 'after';
314
+ this.metadata = 'readonly'; // Reads metadata for server activation
313
315
  this.operations = ['search', 'addNoun'];
314
316
  this.priority = 20;
315
317
  this.conduitAugmentation = null;