305 lines
10 KiB
TypeScript
305 lines
10 KiB
TypeScript
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<Array<{name: string; path: string}>>((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;
|