brainy/src/augmentations/intelligentImport/handlers/imageHandler.ts

351 lines
8.3 KiB
TypeScript
Raw Normal View History

feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
/**
* Image Import Handler
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
*
* Handles image files with:
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
* - EXIF metadata extraction (camera, GPS, timestamps) via exifr
* - Image metadata (dimensions, format) via probe-image-size
* - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
*
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
* NO NATIVE DEPENDENCIES - Pure JavaScript implementation
* Replaces Sharp with lightweight pure-JS alternatives
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
*/
import { BaseFormatHandler } from './base.js'
import type { FormatHandlerOptions, ProcessedData } from '../types.js'
import exifr from 'exifr'
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
import probeImageSize from 'probe-image-size'
import { Readable } from 'stream'
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
export interface ImageMetadata {
/** Image dimensions */
width: number
height: number
/** Image format (jpeg, png, webp, etc.) */
format: string
/** File size in bytes */
size: number
/** Orientation (EXIF) */
orientation?: number
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
/** MIME type */
mimeType?: string
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
}
export interface EXIFData {
/** Camera make (e.g., "Canon", "Nikon") */
make?: string
/** Camera model */
model?: string
/** Lens information */
lens?: string
/** Date/time original */
dateTimeOriginal?: Date
/** GPS latitude */
latitude?: number
/** GPS longitude */
longitude?: number
/** GPS altitude in meters */
altitude?: number
/** Exposure time (e.g., "1/250") */
exposureTime?: number
/** F-number (e.g., 2.8) */
fNumber?: number
/** ISO speed */
iso?: number
/** Focal length in mm */
focalLength?: number
/** Flash fired */
flash?: boolean
/** Copyright */
copyright?: string
/** Artist/photographer */
artist?: string
/** Image description */
imageDescription?: string
/** Software used */
software?: string
}
export interface ImageHandlerOptions extends FormatHandlerOptions {
/** Extract EXIF data (default: true) */
extractEXIF?: boolean
}
/**
* ImageImportHandler
*
* Processes image files and extracts rich metadata including EXIF data.
* Enables developers to import images into the knowledge graph with
* full metadata extraction.
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
*
* Pure JavaScript implementation (no native dependencies)
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
*/
export class ImageHandler extends BaseFormatHandler {
readonly format = 'image'
/**
* Check if this handler can process the given data
*/
canHandle(data: Buffer | string | { filename?: string; ext?: string }): boolean {
// Check by filename/extension
if (typeof data === 'object' && 'filename' in data) {
const mimeType = this.getMimeType(data)
return this.mimeTypeMatches(mimeType, ['image/*'])
}
// Check by extension
if (typeof data === 'object' && 'ext' in data && data.ext) {
return this.isImageExtension(data.ext)
}
// Check by data (Buffer magic bytes)
if (Buffer.isBuffer(data)) {
return this.detectImageFormat(data) !== null
}
return false
}
/**
* Process image file
*/
async process(
data: Buffer | string,
options: ImageHandlerOptions = {}
): Promise<ProcessedData> {
const startTime = Date.now()
try {
// Convert to Buffer
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data, 'base64')
// Extract image metadata
const metadata = await this.extractMetadata(buffer)
// Extract EXIF data (default: enabled)
let exifData: EXIFData | undefined
if (options.extractEXIF !== false) {
exifData = await this.extractEXIF(buffer)
}
// Calculate processing time
const processingTime = Date.now() - startTime
// Generate descriptive name
const imageName = options.filename
? options.filename.replace(/\.[^/.]+$/, '') // Remove extension
: `${metadata.format.toUpperCase()} Image ${metadata.width}x${metadata.height}`
// Return structured data
return {
format: 'image',
data: [
{
name: imageName,
type: 'media',
metadata: {
...metadata,
subtype: 'image',
exif: exifData
}
}
],
metadata: {
rowCount: 1,
fields: ['type', 'metadata'],
processingTime,
imageMetadata: metadata,
exifData
},
filename: options.filename
}
} catch (error) {
throw new Error(
`Image processing failed: ${error instanceof Error ? error.message : String(error)}`
)
}
}
/**
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
* Extract image metadata using probe-image-size (pure JS)
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
*/
private async extractMetadata(buffer: Buffer): Promise<ImageMetadata> {
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
try {
// Convert Buffer to Stream for probe-image-size
const stream = Readable.from(buffer)
const result = await probeImageSize(stream)
return {
width: result.width,
height: result.height,
format: result.type, // 'jpeg', 'png', 'webp', etc.
size: buffer.length,
mimeType: result.mime,
orientation: result.orientation
}
} catch (error) {
// Fallback: Try to detect format from magic bytes
const detectedFormat = this.detectImageFormat(buffer)
return {
width: 0,
height: 0,
format: detectedFormat || 'unknown',
size: buffer.length,
mimeType: detectedFormat ? `image/${detectedFormat}` : undefined
}
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
}
}
/**
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
* Extract EXIF data using exifr (pure JS)
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
*/
private async extractEXIF(buffer: Buffer): Promise<EXIFData | undefined> {
try {
const exif = await exifr.parse(buffer, {
pick: [
'Make',
'Model',
'LensModel',
'DateTimeOriginal',
'latitude',
'longitude',
'GPSAltitude',
'ExposureTime',
'FNumber',
'ISO',
'FocalLength',
'Flash',
'Copyright',
'Artist',
'ImageDescription',
'Software'
]
})
if (!exif) return undefined
return {
make: exif.Make,
model: exif.Model,
lens: exif.LensModel,
dateTimeOriginal: exif.DateTimeOriginal,
latitude: exif.latitude,
longitude: exif.longitude,
altitude: exif.GPSAltitude,
exposureTime: exif.ExposureTime,
fNumber: exif.FNumber,
iso: exif.ISO,
focalLength: exif.FocalLength,
flash: exif.Flash !== undefined ? Boolean(exif.Flash & 1) : undefined,
copyright: exif.Copyright,
artist: exif.Artist,
imageDescription: exif.ImageDescription,
software: exif.Software
}
} catch (error) {
// EXIF extraction can fail for non-JPEG images or corrupt data
return undefined
}
}
/**
* Detect image format from magic bytes
*/
private detectImageFormat(buffer: Buffer): string | null {
if (buffer.length < 4) return null
// JPEG: FF D8 FF
if (buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff) {
return 'jpeg'
}
// PNG: 89 50 4E 47
if (
buffer[0] === 0x89 &&
buffer[1] === 0x50 &&
buffer[2] === 0x4e &&
buffer[3] === 0x47
) {
return 'png'
}
// GIF: 47 49 46
if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {
return 'gif'
}
// WebP: 52 49 46 46 ... 57 45 42 50
if (
buffer[0] === 0x52 &&
buffer[1] === 0x49 &&
buffer[2] === 0x46 &&
buffer[3] === 0x46 &&
buffer.length >= 12 &&
buffer[8] === 0x57 &&
buffer[9] === 0x45 &&
buffer[10] === 0x42 &&
buffer[11] === 0x50
) {
return 'webp'
}
// TIFF: 49 49 2A 00 (little-endian) or 4D 4D 00 2A (big-endian)
if (
(buffer[0] === 0x49 && buffer[1] === 0x49 && buffer[2] === 0x2a && buffer[3] === 0x00) ||
(buffer[0] === 0x4d && buffer[1] === 0x4d && buffer[2] === 0x00 && buffer[3] === 0x2a)
) {
return 'tiff'
}
fix: resolve VFS tree corruption from blob errors (v5.8.0) CRITICAL FIX: Single blob read error no longer corrupts entire VFS tree Root Causes Fixed: 1. Uncaught blob errors in readFile() triggered VFS re-initialization 2. Race conditions in initializeRoot() created duplicate roots 3. Wrong root selection algorithm (oldest vs most children) Architectural Solution: - **Error Isolation**: Blob errors caught and re-thrown as VFSError VFS tree structure completely isolated from file content errors (src/vfs/VirtualFileSystem.ts:288-321) - **Singleton Promise Pattern**: Prevents duplicate root creation Concurrent init() calls wait for same initialization promise Acts as automatic mutex without custom lock class (src/vfs/VirtualFileSystem.ts:180-199) - **Smart Root Selection**: Selects root with MOST children (not oldest) Auto-heals existing duplicates on init() Logs cleanup suggestions for empty roots (src/vfs/VirtualFileSystem.ts:283-334) Production Impact: - Workshop production: 5 duplicate roots, 1,836 files orphaned - After fix: Zero duplicate roots possible, auto-healing - All 100 VFS tests pass ✅ Additional Fix: Remove Sharp native dependency (v5.8.0) ImageHandler rewritten using pure JavaScript: - exifr (already installed) for EXIF extraction - probe-image-size for image dimensions/format - Zero native dependencies (removed 10MB of native binaries) - All 25 image handler tests pass ✅ - No more test crashes from Sharp/libvips worker thread issues Test Results: - VFS tests: 100/100 pass ✅ - Image handler tests: 25/25 pass ✅ - Overall: 1157/1200 tests pass (18 pre-existing timeout issues) - Build: Successful, zero TypeScript errors ✅ Features Complete (TIER 1 - v5.8.0): - Transaction system (36 unit + 35 integration tests) - Duplicate check optimization (O(n) → O(log n)) - GraphIndex pagination - Comprehensive filter documentation
2025-11-14 11:27:35 -08:00
// BMP: 42 4D
if (buffer[0] === 0x42 && buffer[1] === 0x4d) {
return 'bmp'
}
feat: add ImageHandler with EXIF extraction and comprehensive MIME detection (v5.2.0) Implements Phase 1.5 (Comprehensive MIME Type Detection) and adds built-in image processing support to IntelligentImportAugmentation. **New Features:** - ImageHandler: Extracts image metadata (dimensions, format, color space) using sharp - EXIF extraction: Camera data, GPS, timestamps using exifr library - Support for JPEG, PNG, WebP, GIF, TIFF, BMP, SVG, HEIC, AVIF formats - MimeTypeDetector: Unified MIME type detection with magic byte support - FormatDetector: Enhanced with image format detection via MIME + magic bytes **Architecture Fixes:** - Fixed brain.import() augmentation pipeline integration (src/brainy.ts:3140-3154) - Added parameter spreading for ImportSource objects to enable augmentation access - Fixed metadata propagation through ImportCoordinator to final results - Added augmentation data check in ImportCoordinator.extract() **Integration:** - ImageHandler registered as built-in handler alongside CSV, Excel, PDF - Images import as 'media' entities with 'image' subtype - Full metadata preserved in knowledge graph entities - Configuration options: enableImage, extractEXIF, imageDefaults **Test Coverage:** - 15 integration tests (image-import.test.ts) - 100% passing - 27 unit tests (image-handler.test.ts) - 100% passing - Format detection tests for all supported image types - Error handling and resilience tests **Breaking Changes:** None - backward compatible Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:06:17 -08:00
return null
}
/**
* Detect if extension is an image format
*/
private isImageExtension(ext: string): boolean {
const imageExts = [
'.jpg',
'.jpeg',
'.png',
'.gif',
'.webp',
'.tiff',
'.tif',
'.bmp',
'.svg',
'.heic',
'.heif',
'.avif'
]
const normalized = ext.toLowerCase()
const withDot = normalized.startsWith('.') ? normalized : `.${normalized}`
return imageExts.includes(withDot)
}
}