UNPKG

solver-sdk

Version:

SDK for WorkAI API - AI-powered code analysis with WorkCoins billing system

183 lines 7.66 kB
/** * 🚀 Delta-Chunking API клиент * Интеграция с backend endpoints */ /** * API клиент для delta-chunking операций */ export class DeltaChunkingApi { constructor(httpClient) { this.httpClient = httpClient; } /** * Инициализация синхронизации проекта */ async initSync(projectId, request) { const response = await this.httpClient.post(`/api/v1/projects/${projectId}/sync-init`, request); // ✅ ИСПРАВЛЕНО: Проверяем sessionId только если needsSync = true if (response.needsSync && !response.sessionId) { throw new Error('Server did not return sessionId when sync is needed'); } return response; } /** * Отправка батча зашифрованных чанков */ async uploadChunkBatch(projectId, batchRequest) { const response = await this.httpClient.post(`/api/v1/projects/${projectId}/delta-chunks`, batchRequest); return response; } /** * Получение статуса синхронизации */ async getSyncStatus(projectId) { const response = await this.httpClient.get(`/api/v1/projects/${projectId}/sync-status`); return { projectId, sessionId: response.sessionId, status: response.status || 'idle', progress: response.progress || 0, chunksReceived: response.chunksReceived || 0, chunksProcessed: response.chunksProcessed || 0, errorCount: response.errorCount || 0, startedAt: response.startedAt ? new Date(response.startedAt) : undefined, completedAt: response.completedAt ? new Date(response.completedAt) : undefined, lastActivity: response.lastActivity ? new Date(response.lastActivity) : undefined, error: response.error }; } /** * Завершение синхронизации */ async finalizeSync(projectId) { const response = await this.httpClient.post(`/api/v1/projects/${projectId}/sync-finalize`, {}); return { success: response.success || false, projectId, sessionId: response.sessionId, processedChunks: response.processedChunks || 0, totalChunks: response.totalChunks || 0, duration: response.duration || 0, error: response.error, details: response.details }; } /** * Отмена синхронизации */ async cancelSync(projectId) { const response = await this.httpClient.delete(`/api/v1/projects/${projectId}/sync-cancel`); return { success: response.success || false, message: response.message }; } /** * Batch upload с retry логикой */ async uploadChunksWithRetry(projectId, chunks, options = {}) { const { batchSize = 50, maxRetries = 3, onProgress } = options; const totalChunks = chunks.length; const totalBatches = Math.ceil(totalChunks / batchSize); let processedChunks = 0; let failedChunks = 0; const errors = []; for (let batchIndex = 0; batchIndex < totalBatches; batchIndex++) { const startIdx = batchIndex * batchSize; const endIdx = Math.min(startIdx + batchSize, totalChunks); const batchChunks = chunks.slice(startIdx, endIdx); const batchRequest = { batchIndex, totalBatches, chunks: batchChunks }; let success = false; let retryCount = 0; while (!success && retryCount < maxRetries) { try { const result = await this.uploadChunkBatch(projectId, batchRequest); processedChunks += result.processed; failedChunks += result.failed; if (result.errors) { errors.push(...result.errors); } success = true; // Уведомляем о прогрессе if (onProgress) { onProgress(processedChunks, totalChunks); } } catch (error) { retryCount++; if (retryCount >= maxRetries) { const errorMessage = error instanceof Error ? error.message : String(error); errors.push(`Batch ${batchIndex} failed after ${maxRetries} retries: ${errorMessage}`); failedChunks += batchChunks.length; } else { // Экспоненциальная задержка перед повтором await new Promise(resolve => setTimeout(resolve, Math.pow(2, retryCount) * 1000)); } } } } return { success: failedChunks === 0, projectId, processedChunks, totalChunks, duration: 0, // Будет заполнено на уровне SDK error: errors.length > 0 ? errors.join('; ') : undefined, details: { newFiles: 0, // Будет заполнено на уровне SDK changedFiles: 0, deletedFiles: 0 } }; } /** * Очистка удаленных файлов из векторной базы * @param projectId ID проекта * @param activeFiles Список активных файлов (оставшихся после удаления) * @param deletedFiles ОПЦИОНАЛЬНО: Явно удаленные файлы (пути) */ async cleanupFiles(projectId, activeFiles, deletedFiles) { const response = await this.httpClient.post(`/api/v1/projects/${projectId}/cleanup-files`, { activeFiles, deletedFiles }); return response; } /** * Инвалидировать chunks измененного файла */ async invalidateFile(projectId, options) { const response = await this.httpClient.post(`/api/v1/projects/${projectId}/delta/invalidate-file`, { filePath: options.filePath, reason: options.reason || 'file_changed' }); return { success: response.success !== false, chunksInvalidated: response.chunksInvalidated || 0, cacheInvalidated: response.cacheInvalidated !== false, filePath: response.filePath || options.filePath }; } /** * Batch инвалидация chunks для нескольких файлов * (для предотвращения rate limiting) */ async invalidateFiles(projectId, files) { const response = await this.httpClient.post(`/api/v1/projects/${projectId}/delta/invalidate-files`, { files: files.map(f => ({ filePath: f.filePath, reason: f.reason || 'file_changed' })) }); return { success: response.success !== false, totalFiles: response.totalFiles || files.length, totalChunksInvalidated: response.totalChunksInvalidated || 0, totalCacheInvalidated: response.totalCacheInvalidated || 0, results: response.results || [] }; } } //# sourceMappingURL=delta-chunking-api.js.map