// Location: src/services/migration/ChromaDataLoader.ts
// Loads data from existing ChromaDB collections for migration to new JSON structure
// Used by: DataMigrationService to read legacy ChromaDB collection data
// Dependencies: FileSystemService for ChromaDB collection file reading
import { FileSystemService } from '../storage/FileSystemService';
import { BRAND_NAME } from '../../constants/branding';
export interface ChromaCollectionData {
memoryTraces: any[];
sessions: any[];
conversations: any[];
workspaces: any[];
snapshots: any[];
}
export class ChromaDataLoader {
private fileSystem: FileSystemService;
constructor(fileSystem: FileSystemService) {
this.fileSystem = fileSystem;
}
async loadAllCollections(): Promise<ChromaCollectionData> {
const [memoryTraces, sessions, conversations, workspaces, snapshots] = await Promise.all([
this.fileSystem.readChromaCollection('memory_traces'),
this.fileSystem.readChromaCollection('sessions'),
this.fileSystem.readChromaCollection('chat_conversations'),
this.fileSystem.readChromaCollection('workspaces'),
this.fileSystem.readChromaCollection('snapshots')
]);
return {
memoryTraces,
sessions,
conversations,
workspaces,
snapshots
};
}
async detectLegacyData(): Promise<boolean> {
try {
const collections = await this.loadAllCollections();
return Object.values(collections).some(collection =>
Array.isArray(collection) && collection.length > 0
);
} catch {
return false;
}
}
/**
* Get summary statistics about the legacy data
*/
async getDataSummary(): Promise<{
totalItems: number;
collections: Record<string, number>;
oldestItem?: number;
newestItem?: number;
}> {
const collections = await this.loadAllCollections();
let totalItems = 0;
let oldestTimestamp: number | undefined;
let newestTimestamp: number | undefined;
const collectionCounts: Record<string, number> = {};
for (const [collectionName, items] of Object.entries(collections)) {
collectionCounts[collectionName] = items.length;
totalItems += items.length;
// Find timestamp ranges
for (const item of items) {
const timestamp = item.metadata?.timestamp ||
item.metadata?.created ||
item.metadata?.created;
if (timestamp) {
if (!oldestTimestamp || timestamp < oldestTimestamp) {
oldestTimestamp = timestamp;
}
if (!newestTimestamp || timestamp > newestTimestamp) {
newestTimestamp = timestamp;
}
}
}
}
return {
totalItems,
collections: collectionCounts,
oldestItem: oldestTimestamp,
newestItem: newestTimestamp
};
}
/**
* Test if ChromaDB collection files are accessible
*/
async testCollectionAccess(): Promise<{
accessible: string[];
missing: string[];
errors: string[];
}> {
const collectionNames = ['memory_traces', 'sessions', 'chat_conversations', 'workspaces', 'snapshots'];
const accessible: string[] = [];
const missing: string[] = [];
const errors: string[] = [];
for (const collectionName of collectionNames) {
try {
const items = await this.fileSystem.readChromaCollection(collectionName);
if (Array.isArray(items)) {
accessible.push(collectionName);
} else {
missing.push(collectionName);
}
} catch (error) {
errors.push(`${collectionName}: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
}
return { accessible, missing, errors };
}
}