@soulcraft/brainy 5.1.1 → 5.2.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.
@@ -133,7 +133,8 @@ export class ImportCoordinator {
133
133
  groupBy: opts.groupBy,
134
134
  customGrouping: opts.customGrouping,
135
135
  preserveSource: opts.preserveSource,
136
- sourceBuffer: normalizedSource.type === 'buffer' ? normalizedSource.data : undefined,
136
+ // v5.1.2: Fix sourceBuffer for file paths - type is 'path' not 'buffer' from normalizeSource()
137
+ sourceBuffer: Buffer.isBuffer(normalizedSource.data) ? normalizedSource.data : undefined,
137
138
  sourceFilename: normalizedSource.filename || `import.${detection.format}`,
138
139
  createRelationshipFile: true,
139
140
  createMetadataFile: true,
@@ -366,6 +367,37 @@ export class ImportCoordinator {
366
367
  * Extract entities using format-specific importer
367
368
  */
368
369
  async extract(source, format, options) {
370
+ // v5.2.0: Check if IntelligentImportAugmentation already extracted data
371
+ if (options._intelligentImport && options._extractedData) {
372
+ const extractedData = options._extractedData;
373
+ // Convert extracted data to ExtractedRow format
374
+ const rows = extractedData.map((item) => ({
375
+ entity: {
376
+ id: item.id || `entity-${Date.now()}-${Math.random()}`,
377
+ name: item.name || item.type || 'Unnamed',
378
+ type: item.type || 'unknown',
379
+ description: item.description || '',
380
+ confidence: 1.0,
381
+ metadata: item.metadata || {}
382
+ },
383
+ relatedEntities: [],
384
+ relationships: []
385
+ }));
386
+ return {
387
+ rows,
388
+ entities: extractedData,
389
+ relationships: [],
390
+ metadata: options._metadata?.intelligentImport || {},
391
+ stats: {
392
+ byType: {},
393
+ byConfidence: {}
394
+ },
395
+ rowsProcessed: extractedData.length,
396
+ entitiesExtracted: extractedData.length,
397
+ relationshipsInferred: 0,
398
+ processingTime: 0
399
+ };
400
+ }
369
401
  const extractOptions = {
370
402
  enableNeuralExtraction: options.enableNeuralExtraction !== false,
371
403
  enableRelationshipInference: options.enableRelationshipInference !== false,
@@ -427,6 +459,41 @@ export class ImportCoordinator {
427
459
  ? source.data
428
460
  : Buffer.from(JSON.stringify(source.data));
429
461
  return await this.docxImporter.extract(docxBuffer, extractOptions);
462
+ case 'image':
463
+ // v5.2.0: Images are handled by IntelligentImportAugmentation
464
+ // If we reach here, augmentation didn't process it - return minimal result
465
+ const imageName = source.filename || 'image';
466
+ const imageId = `image-${Date.now()}`;
467
+ return {
468
+ rows: [{
469
+ entity: {
470
+ id: imageId,
471
+ name: imageName,
472
+ type: 'media',
473
+ description: '',
474
+ confidence: 1.0,
475
+ metadata: { subtype: 'image' }
476
+ },
477
+ relatedEntities: [],
478
+ relationships: []
479
+ }],
480
+ entities: [{
481
+ id: imageId,
482
+ name: imageName,
483
+ type: 'media',
484
+ metadata: { subtype: 'image' }
485
+ }],
486
+ relationships: [],
487
+ metadata: {},
488
+ stats: {
489
+ byType: { media: 1 },
490
+ byConfidence: { high: 1 }
491
+ },
492
+ rowsProcessed: 1,
493
+ entitiesExtracted: 1,
494
+ relationshipsInferred: 0,
495
+ processingTime: 0
496
+ };
430
497
  default:
431
498
  throw new Error(`Unsupported format: ${format}`);
432
499
  }
@@ -567,7 +634,8 @@ export class ImportCoordinator {
567
634
  id: entityId,
568
635
  name: entity.name,
569
636
  type: entity.type,
570
- vfsPath: vfsFile?.path
637
+ vfsPath: vfsFile?.path,
638
+ metadata: entity.metadata // v5.2.0: Include metadata in return (for ImageHandler, etc)
571
639
  });
572
640
  newCount++;
573
641
  }
@@ -658,7 +726,8 @@ export class ImportCoordinator {
658
726
  id: entityId,
659
727
  name: entity.name,
660
728
  type: entity.type,
661
- vfsPath: vfsFile?.path
729
+ vfsPath: vfsFile?.path,
730
+ metadata: entity.metadata // v5.2.0: Include metadata in return (for ImageHandler, etc)
662
731
  });
663
732
  // ============================================
664
733
  // v4.9.0: Create provenance relationship (document → entity)
@@ -0,0 +1,81 @@
1
+ /**
2
+ * MIME Type Detection Service (v5.2.0)
3
+ *
4
+ * Provides comprehensive MIME type detection using:
5
+ * 1. Industry-standard `mime` library (2000+ IANA types)
6
+ * 2. Custom mappings for developer-specific files
7
+ *
8
+ * Replaces hardcoded MIME dictionaries with maintainable, extensible solution.
9
+ */
10
+ /**
11
+ * MIME Type Detector with comprehensive file type coverage
12
+ *
13
+ * Handles 2000+ standard types plus custom developer formats
14
+ */
15
+ export declare class MimeTypeDetector {
16
+ private customTypes;
17
+ constructor();
18
+ /**
19
+ * Detect MIME type from filename
20
+ *
21
+ * @param filename - File name with extension
22
+ * @param content - Optional file content (for future content-based detection)
23
+ * @returns MIME type string (e.g., 'text/typescript', 'application/json')
24
+ */
25
+ detectMimeType(filename: string, content?: Buffer): string;
26
+ /**
27
+ * Check if MIME type represents a text file
28
+ *
29
+ * Text files get full content embeddings for semantic search.
30
+ * Binary files get description-only embeddings.
31
+ *
32
+ * @param mimeType - MIME type string
33
+ * @returns true if text file, false if binary
34
+ */
35
+ isTextFile(mimeType: string): boolean;
36
+ /**
37
+ * Get file extension from filename
38
+ *
39
+ * @param filename - File name
40
+ * @returns Extension with dot (e.g., '.ts') or undefined
41
+ */
42
+ private getExtension;
43
+ /**
44
+ * Get basename from filename (without path)
45
+ *
46
+ * @param filename - Full file path or name
47
+ * @returns Basename (e.g., 'Dockerfile' from '/path/to/Dockerfile')
48
+ */
49
+ private getBasename;
50
+ /**
51
+ * Normalize filename for special cases
52
+ *
53
+ * Handles files like 'Dockerfile', 'Makefile', '.gitignore'
54
+ *
55
+ * @param filename - Original filename
56
+ * @returns Normalized filename with extension if special case
57
+ */
58
+ private normalizeFilename;
59
+ /**
60
+ * Check if filename is a special case (no extension but known type)
61
+ *
62
+ * @param basename - File basename
63
+ * @returns true if special filename
64
+ */
65
+ private isSpecialFilename;
66
+ /**
67
+ * Get MIME type for special filename
68
+ *
69
+ * @param basename - File basename
70
+ * @returns MIME type
71
+ */
72
+ private getSpecialFilenameType;
73
+ }
74
+ /**
75
+ * Singleton instance for global use
76
+ *
77
+ * Usage:
78
+ * import { mimeDetector } from './MimeTypeDetector'
79
+ * const type = mimeDetector.detectMimeType('file.ts')
80
+ */
81
+ export declare const mimeDetector: MimeTypeDetector;
@@ -0,0 +1,262 @@
1
+ /**
2
+ * MIME Type Detection Service (v5.2.0)
3
+ *
4
+ * Provides comprehensive MIME type detection using:
5
+ * 1. Industry-standard `mime` library (2000+ IANA types)
6
+ * 2. Custom mappings for developer-specific files
7
+ *
8
+ * Replaces hardcoded MIME dictionaries with maintainable, extensible solution.
9
+ */
10
+ import mime from 'mime';
11
+ /**
12
+ * MIME Type Detector with comprehensive file type coverage
13
+ *
14
+ * Handles 2000+ standard types plus custom developer formats
15
+ */
16
+ export class MimeTypeDetector {
17
+ constructor() {
18
+ // Custom MIME types for developer-specific files not in IANA registry
19
+ this.customTypes = new Map([
20
+ // Shell scripts (various shells)
21
+ ['.bash', 'text/x-shellscript'],
22
+ ['.zsh', 'text/x-shellscript'],
23
+ ['.fish', 'text/x-shellscript'],
24
+ ['.ksh', 'text/x-shellscript'],
25
+ ['.csh', 'application/x-csh'], // IANA registered
26
+ // Core programming languages (override mime library)
27
+ ['.ts', 'text/typescript'],
28
+ ['.tsx', 'text/typescript'],
29
+ ['.js', 'text/javascript'],
30
+ ['.jsx', 'text/javascript'],
31
+ ['.mjs', 'text/javascript'],
32
+ ['.py', 'text/x-python'],
33
+ ['.go', 'text/x-go'],
34
+ ['.rs', 'text/x-rust'],
35
+ ['.java', 'text/x-java'],
36
+ ['.c', 'text/x-c'],
37
+ ['.cpp', 'text/x-c++'],
38
+ ['.cc', 'text/x-c++'],
39
+ ['.cxx', 'text/x-c++'],
40
+ ['.c++', 'text/x-c++'],
41
+ ['.h', 'text/x-c'],
42
+ ['.hpp', 'text/x-c++'],
43
+ // Data formats (override mime library for consistency)
44
+ ['.xml', 'text/xml'],
45
+ // Modern programming languages
46
+ ['.kt', 'text/x-kotlin'],
47
+ ['.kts', 'text/x-kotlin'],
48
+ ['.swift', 'text/x-swift'],
49
+ ['.dart', 'text/x-dart'],
50
+ ['.lua', 'text/x-lua'],
51
+ ['.scala', 'text/x-scala'],
52
+ ['.r', 'text/x-r'],
53
+ // Configuration files
54
+ ['.env', 'text/x-env'],
55
+ ['.ini', 'text/x-ini'],
56
+ ['.conf', 'text/plain'],
57
+ ['.properties', 'text/x-java-properties'],
58
+ ['.config', 'text/plain'],
59
+ ['.editorconfig', 'text/plain'],
60
+ ['.gitignore', 'text/plain'],
61
+ ['.dockerignore', 'text/plain'],
62
+ ['.npmignore', 'text/plain'],
63
+ ['.eslintrc', 'application/json'],
64
+ ['.prettierrc', 'application/json'],
65
+ // Build/project files
66
+ ['.gradle', 'text/x-gradle'],
67
+ ['.cmake', 'text/x-cmake'],
68
+ ['.dockerfile', 'text/x-dockerfile'],
69
+ // Web framework components
70
+ ['.vue', 'text/x-vue'],
71
+ ['.svelte', 'text/x-svelte'],
72
+ ['.astro', 'text/x-astro'],
73
+ // Style preprocessors
74
+ ['.scss', 'text/x-scss'],
75
+ ['.sass', 'text/x-sass'],
76
+ ['.less', 'text/x-less'],
77
+ ['.styl', 'text/x-stylus'],
78
+ // Big data / modern data formats
79
+ ['.parquet', 'application/vnd.apache.parquet'],
80
+ ['.avro', 'application/avro'],
81
+ ['.proto', 'text/x-protobuf'],
82
+ ['.arrow', 'application/vnd.apache.arrow.file'],
83
+ ['.msgpack', 'application/msgpack'],
84
+ ['.cbor', 'application/cbor'],
85
+ // Additional programming languages
86
+ ['.m', 'text/x-objective-c'],
87
+ ['.vim', 'text/x-vim'],
88
+ ['.ex', 'text/x-elixir'],
89
+ ['.exs', 'text/x-elixir'],
90
+ ['.clj', 'text/x-clojure'],
91
+ ['.cljs', 'text/x-clojure'],
92
+ ['.hs', 'text/x-haskell'],
93
+ ['.erl', 'text/x-erlang'],
94
+ // Markup/documentation
95
+ ['.rst', 'text/x-rst'],
96
+ ['.rest', 'text/x-rst'],
97
+ ['.adoc', 'text/x-asciidoc'],
98
+ ['.asciidoc', 'text/x-asciidoc'],
99
+ // Office formats (OpenXML - Microsoft Office)
100
+ ['.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
101
+ ['.docm', 'application/vnd.ms-word.document.macroEnabled.12'],
102
+ ['.dotx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.template'],
103
+ ['.xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
104
+ ['.xlsm', 'application/vnd.ms-excel.sheet.macroEnabled.12'],
105
+ ['.xltx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.template'],
106
+ ['.xlsb', 'application/vnd.ms-excel.sheet.binary.macroEnabled.12'],
107
+ ['.pptx', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'],
108
+ ['.pptm', 'application/vnd.ms-powerpoint.presentation.macroEnabled.12'],
109
+ // Office formats (ODF - OpenDocument)
110
+ ['.odt', 'application/vnd.oasis.opendocument.text'],
111
+ ['.ods', 'application/vnd.oasis.opendocument.spreadsheet'],
112
+ ['.odp', 'application/vnd.oasis.opendocument.presentation'],
113
+ ['.odg', 'application/vnd.oasis.opendocument.graphics'],
114
+ ['.odf', 'application/vnd.oasis.opendocument.formula'],
115
+ ['.odb', 'application/vnd.oasis.opendocument.database']
116
+ ]);
117
+ }
118
+ /**
119
+ * Detect MIME type from filename
120
+ *
121
+ * @param filename - File name with extension
122
+ * @param content - Optional file content (for future content-based detection)
123
+ * @returns MIME type string (e.g., 'text/typescript', 'application/json')
124
+ */
125
+ detectMimeType(filename, content) {
126
+ // Normalize filename for special cases
127
+ const normalizedFilename = this.normalizeFilename(filename);
128
+ const ext = this.getExtension(normalizedFilename);
129
+ // 1. Check custom types first (highest priority)
130
+ if (ext && this.customTypes.has(ext)) {
131
+ return this.customTypes.get(ext);
132
+ }
133
+ // 2. Use mime library for standard IANA types
134
+ const standardType = mime.getType(normalizedFilename);
135
+ if (standardType) {
136
+ return standardType;
137
+ }
138
+ // 3. Special handling for files without extensions
139
+ const basename = this.getBasename(filename);
140
+ if (this.isSpecialFilename(basename)) {
141
+ return this.getSpecialFilenameType(basename);
142
+ }
143
+ // 4. Fallback to generic binary
144
+ return 'application/octet-stream';
145
+ }
146
+ /**
147
+ * Check if MIME type represents a text file
148
+ *
149
+ * Text files get full content embeddings for semantic search.
150
+ * Binary files get description-only embeddings.
151
+ *
152
+ * @param mimeType - MIME type string
153
+ * @returns true if text file, false if binary
154
+ */
155
+ isTextFile(mimeType) {
156
+ return (mimeType.startsWith('text/') ||
157
+ mimeType.includes('json') ||
158
+ mimeType.includes('javascript') ||
159
+ mimeType.includes('typescript') ||
160
+ mimeType.includes('xml') ||
161
+ mimeType.includes('yaml') ||
162
+ mimeType.includes('sql') ||
163
+ mimeType === 'application/json' ||
164
+ mimeType === 'application/xml');
165
+ }
166
+ /**
167
+ * Get file extension from filename
168
+ *
169
+ * @param filename - File name
170
+ * @returns Extension with dot (e.g., '.ts') or undefined
171
+ */
172
+ getExtension(filename) {
173
+ const lastDot = filename.lastIndexOf('.');
174
+ if (lastDot === -1 || lastDot === 0)
175
+ return undefined;
176
+ return filename.substring(lastDot).toLowerCase();
177
+ }
178
+ /**
179
+ * Get basename from filename (without path)
180
+ *
181
+ * @param filename - Full file path or name
182
+ * @returns Basename (e.g., 'Dockerfile' from '/path/to/Dockerfile')
183
+ */
184
+ getBasename(filename) {
185
+ const lastSlash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'));
186
+ return lastSlash === -1 ? filename : filename.substring(lastSlash + 1);
187
+ }
188
+ /**
189
+ * Normalize filename for special cases
190
+ *
191
+ * Handles files like 'Dockerfile', 'Makefile', '.gitignore'
192
+ *
193
+ * @param filename - Original filename
194
+ * @returns Normalized filename with extension if special case
195
+ */
196
+ normalizeFilename(filename) {
197
+ const basename = this.getBasename(filename).toLowerCase();
198
+ // Special files without extensions
199
+ const specialFiles = {
200
+ 'dockerfile': '.dockerfile',
201
+ 'makefile': '.makefile',
202
+ 'gemfile': '.gemfile',
203
+ 'rakefile': '.rakefile',
204
+ 'vagrantfile': '.vagrantfile'
205
+ };
206
+ if (specialFiles[basename]) {
207
+ return filename + specialFiles[basename];
208
+ }
209
+ return filename;
210
+ }
211
+ /**
212
+ * Check if filename is a special case (no extension but known type)
213
+ *
214
+ * @param basename - File basename
215
+ * @returns true if special filename
216
+ */
217
+ isSpecialFilename(basename) {
218
+ const lower = basename.toLowerCase();
219
+ return (lower === 'dockerfile' ||
220
+ lower === 'makefile' ||
221
+ lower === 'gemfile' ||
222
+ lower === 'rakefile' ||
223
+ lower === 'vagrantfile' ||
224
+ lower === '.env' ||
225
+ lower === '.editorconfig' ||
226
+ lower.startsWith('.git') ||
227
+ lower.startsWith('.npm') ||
228
+ lower.startsWith('.docker') ||
229
+ lower.startsWith('.eslint') ||
230
+ lower.startsWith('.prettier'));
231
+ }
232
+ /**
233
+ * Get MIME type for special filename
234
+ *
235
+ * @param basename - File basename
236
+ * @returns MIME type
237
+ */
238
+ getSpecialFilenameType(basename) {
239
+ const lower = basename.toLowerCase();
240
+ if (lower === 'dockerfile')
241
+ return 'text/x-dockerfile';
242
+ if (lower === 'makefile')
243
+ return 'text/x-makefile';
244
+ if (lower === 'gemfile' || lower === 'rakefile')
245
+ return 'text/x-ruby';
246
+ if (lower === 'vagrantfile')
247
+ return 'text/x-ruby';
248
+ if (lower === '.env')
249
+ return 'text/x-env';
250
+ // Other dotfiles are usually config files
251
+ return 'text/plain';
252
+ }
253
+ }
254
+ /**
255
+ * Singleton instance for global use
256
+ *
257
+ * Usage:
258
+ * import { mimeDetector } from './MimeTypeDetector'
259
+ * const type = mimeDetector.detectMimeType('file.ts')
260
+ */
261
+ export const mimeDetector = new MimeTypeDetector();
262
+ //# sourceMappingURL=MimeTypeDetector.js.map
@@ -30,6 +30,10 @@ export declare class VirtualFileSystem implements IVirtualFileSystem {
30
30
  private backgroundTimer;
31
31
  private mkdirLocks;
32
32
  constructor(brain?: Brainy);
33
+ /**
34
+ * v5.2.0: Access to BlobStorage for unified file storage
35
+ */
36
+ private get blobStorage();
33
37
  /**
34
38
  * Initialize the VFS
35
39
  */
@@ -130,18 +134,7 @@ export declare class VirtualFileSystem implements IVirtualFileSystem {
130
134
  private getParentPath;
131
135
  private getBasename;
132
136
  private getExtension;
133
- private detectMimeType;
134
- private isTextFile;
135
137
  private getFileNounType;
136
- private shouldCompress;
137
- private readExternalContent;
138
- private storeExternalContent;
139
- private deleteExternalContent;
140
- private readChunkedContent;
141
- private storeChunkedContent;
142
- private deleteChunkedContent;
143
- private compress;
144
- private decompress;
145
138
  private generateEmbedding;
146
139
  private extractMetadata;
147
140
  private updateAccessTime;