import { ipcMain } from 'electron'; import { DocumentMetadata, LLMConfig, ServiceError } from '../types'; const fs = require('fs'); const path = require('path'); const os = require('os'); interface IpcHandlerParams { _: unknown; dirPath?: string; path?: string; question?: string; config?: LLMConfig; content?: string; metadata?: DocumentMetadata; } export function setupIpcHandlers() { // File System Handlers ipcMain.handle('start-watching', async (_: unknown, dirPath: string) => { try { await (await import('../services/fileSystem')).fileSystemService.startWatching(dirPath); return { success: true }; } catch (error) { const err = error as Error; console.error('Error starting watch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('stop-watching', async (_: unknown, dirPath: string) => { try { await (await import('../services/fileSystem')).fileSystemService.stopWatching(dirPath); return { success: true }; } catch (error) { const err = error as Error; console.error('Error stopping watch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('add-excluded-path', async (_: unknown, path: string) => { try { (await import('../services/fileSystem')).fileSystemService.addExcludedPath(path); return { success: true }; } catch (error) { const err = error as Error; console.error('Error adding excluded path:', err); return { success: false, error: err.message }; } }); // LLM Handlers ipcMain.handle('query-llm', async (event, question: string) => { try { const webContents = event.sender; const response = await (await import('../services/llmService')).llmService.query( question, (chunk: string) => { webContents.send('llm-response-chunk', chunk); } ); return response; } catch (error) { const err = error as Error; console.error('Error querying LLM:', err); throw err; } }); ipcMain.handle('get-llm-config', async () => { try { const config = (await import('../services/llmService')).llmService.getConfig(); return { success: true, data: config }; } catch (error) { const err = error as Error; console.error('Error getting LLM config:', err); return { success: false, error: err.message }; } }); // Ollama Operations ipcMain.handle('check-ollama', async () => { try { const status = await (await import('../services/ollamaService')).ollamaService.checkOllamaInstallation(); return status; } catch (error) { const err = error as Error; console.error('Error checking Ollama:', err); throw err; } }); // Model Operations ipcMain.handle('check-model', async (_: unknown, modelName: string) => { try { const status = await (await import('../services/ollamaService')).ollamaService.checkModel(modelName); return status; } catch (error) { const err = error as Error; console.error('Error checking model:', err); throw err; } }); ipcMain.handle('pull-model', async (event, modelName: string) => { try { console.log('Starting model pull in IPC handler for:', modelName); const webContents = event.sender; // Create a wrapper for the progress callback that includes error handling const progressCallback = (status: string) => { try { console.log('Sending progress update:', status); webContents.send(`pull-model-progress-${modelName}`, status); } catch (err) { console.error('Error sending progress update:', err); } }; // Attempt to pull the model await (await import('../services/ollamaService')).ollamaService.pullModel( modelName, progressCallback ); // If we get here, the pull was successful and verified console.log('Model pull completed successfully'); return { success: true }; } catch (error) { const err = error as Error; console.error('Error pulling model:', err); // Return a structured error response return { success: false, error: err.message || 'Failed to install model', details: err instanceof Error ? err.stack : undefined }; } }); ipcMain.handle('get-documents', async () => { try { const documents = (await import('../services/vectorStore')).vectorStoreService.getDocuments(); return { success: true, data: documents }; } catch (error) { const err = error as Error; console.error('Error getting documents:', err); return { success: false, error: err.message }; } }); // Vector Store Handlers ipcMain.handle('add-document', async (_: unknown, content: string, metadata: DocumentMetadata) => { try { await (await import('../services/vectorStore')).vectorStoreService.addDocument(content, metadata); return { success: true }; } catch (error) { const err = error as Error; console.error('Error adding document:', err); return { success: false, error: err.message }; } }); ipcMain.handle('delete-document', async (_: unknown, path: string) => { try { await (await import('../services/vectorStore')).vectorStoreService.deleteDocument(path); return { success: true }; } catch (error) { const err = error as Error; console.error('Error deleting document:', err); return { success: false, error: err.message }; } }); ipcMain.handle('update-document', async (_: unknown, content: string, metadata: DocumentMetadata) => { try { await (await import('../services/vectorStore')).vectorStoreService.updateDocument(content, metadata); return { success: true }; } catch (error) { const err = error as Error; console.error('Error updating document:', err); return { success: false, error: err.message }; } }); ipcMain.handle('get-user-home', async () => { try { const homeDir = os.homedir(); return { success: true, data: homeDir }; } catch (error) { const err = error as Error; console.error('Error getting user home:', err); return { success: false, error: err.message }; } }); ipcMain.handle('list-directories', async (_: unknown, dirPath: string) => { try { const directories = await new Promise>((resolve, reject) => { fs.readdir(dirPath, { withFileTypes: true }, (err, items) => { if (err) { reject(err); return; } const folders = items .filter(item => item.isDirectory()) .map(item => ({ name: item.name, path: path.join(dirPath, item.name) })); resolve(folders); }); }); return { success: true, data: directories }; } catch (error) { const err = error as Error; console.error('Error listing directories:', err); return { success: false, error: err.message }; } }); // Meilisearch Handlers ipcMain.handle('meilisearch-add-documents', async (_: unknown, indexName: string, documents: any[]) => { try { await (global as any).meilisearchService.addDocuments(indexName, documents); return { success: true }; } catch (error) { const err = error as Error; console.error('Error adding documents to Meilisearch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('meilisearch-remove-documents', async (_: unknown, indexName: string, documentIds: string[]) => { try { await (global as any).meilisearchService.removeDocuments(indexName, documentIds); return { success: true }; } catch (error) { const err = error as Error; console.error('Error removing documents from Meilisearch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('meilisearch-update-documents', async (_: unknown, indexName: string, documents: any[]) => { try { await (global as any).meilisearchService.updateDocuments(indexName, documents); return { success: true }; } catch (error) { const err = error as Error; console.error('Error updating documents in Meilisearch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('meilisearch-create-index', async (_: unknown, indexName: string) => { try { await (global as any).meilisearchService.createIndex(indexName); return { success: true }; } catch (error) { const err = error as Error; console.error('Error creating index in Meilisearch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('meilisearch-delete-index', async (_: unknown, indexName: string) => { try { await (global as any).meilisearchService.deleteIndex(indexName); return { success: true }; } catch (error) { const err = error as Error; console.error('Error deleting index in Meilisearch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('meilisearch-get-documents', async (_: unknown, indexName: string) => { try { const documents = await (global as any).meilisearchService.getDocuments(indexName); return { success: true, data: documents }; } catch (error) { const err = error as Error; console.error('Error getting documents from Meilisearch:', err); return { success: false, error: err.message }; } }); ipcMain.handle('meilisearch-search', async (_: unknown, indexName: string, query: string) => { try { const results = await (global as any).meilisearchService.search(indexName, query); return { success: true, data: results }; } catch (error) { const err = error as Error; console.error('Error searching Meilisearch:', err); return { success: false, error: err.message }; } }); } export default setupIpcHandlers;