Add Google Takeout data import infrastructure

Implements Phase 1 & 2 of Google Takeout RAG integration:
- Database migrations for calendar_events, location_history, search_history
- DAO implementations with hybrid time + semantic search
- Parsers for .ics, JSON, and HTML Google Takeout formats
- Import utilities with batch insert optimization

Features:
- CalendarEventDao: Hybrid time-range + semantic search for events
- LocationHistoryDao: GPS proximity with Haversine distance calculation
- SearchHistoryDao: Semantic-first search (queries are embedding-rich)
- Batch inserts for performance (1M+ records in minutes vs hours)
- OpenTelemetry tracing for all database operations

Import utilities:
- import_calendar: Parse .ics with optional embedding generation
- import_location_history: High-volume GPS data with batch inserts
- import_search_history: Always generates embeddings for semantic search

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Cameron
2026-01-05 14:50:49 -05:00
parent bb23e6bb25
commit d86b2c3746
27 changed files with 3129 additions and 55 deletions

View File

@@ -298,17 +298,17 @@ impl From<ImageExif> for ExifMetadata {
},
gps: if has_gps {
Some(GpsCoordinates {
latitude: exif.gps_latitude,
longitude: exif.gps_longitude,
altitude: exif.gps_altitude,
latitude: exif.gps_latitude.map(|v| v as f64),
longitude: exif.gps_longitude.map(|v| v as f64),
altitude: exif.gps_altitude.map(|v| v as f64),
})
} else {
None
},
capture_settings: if has_capture_settings {
Some(CaptureSettings {
focal_length: exif.focal_length,
aperture: exif.aperture,
focal_length: exif.focal_length.map(|v| v as f64),
aperture: exif.aperture.map(|v| v as f64),
shutter_speed: exif.shutter_speed,
iso: exif.iso,
})