solver-sdk 5.4.0 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,34 +12,40 @@ npm install solver-sdk
12
12
 
13
13
  ## 🚀 Быстрый старт
14
14
 
15
- ```javascript
15
+ ```typescript
16
16
  import { CodeSolverSDK } from 'solver-sdk';
17
17
 
18
18
  const sdk = new CodeSolverSDK({
19
19
  baseURL: 'http://localhost:3000',
20
20
  apiKey: 'your-api-key',
21
- webSocket: { enabled: true } // Включить WebSocket для real-time уведомлений
21
+ webSocket: { enabled: true }
22
22
  });
23
23
 
24
- // Подключение к WebSocket
25
- await sdk.connectWebSocket();
26
-
27
- // Создание проекта
28
- const project = await sdk.projects.createProject('My Project', '/path/to/project');
29
-
30
- // Запуск индексации с real-time статусом
31
- const indexResult = await sdk.indexing.indexProject('/path', 'My Project');
32
-
33
- // Подписка на real-time уведомления
34
- sdk.projectSync.on('sync-status-update', (status) => {
35
- console.log(`Индексация: ${status.progress}%`);
36
- });
37
-
38
- // Поиск по коду
39
- const results = await sdk.search.searchCode(project.id, {
40
- query: 'function authenticate',
41
- limit: 10
42
- });
24
+ // 🔄 Cursor-like workflow для VS Code расширения
25
+ async function openProject(projectPath: string) {
26
+ // 1. Создать/найти проект
27
+ const project = await sdk.projects.findOrCreateProject(projectPath, projectName);
28
+
29
+ // 2. Проверить прерванные сессии
30
+ const recovery = await sdk.projects.getRecoveryStatus(project.id);
31
+ if (recovery.hasInterruptedSession) {
32
+ // Показать диалог: "Continue indexing (67%)" или "Start fresh"
33
+ const choice = await showRecoveryDialog(recovery.recoveryInfo);
34
+ if (choice === 'continue') {
35
+ await sdk.projects.resumeSync(project.id);
36
+ } else {
37
+ await sdk.projects.cancelRecovery(project.id);
38
+ }
39
+ }
40
+
41
+ // 3. Smart Sync - проверить нужна ли синхронизация
42
+ const hash = await computeMerkleRootHash(projectPath);
43
+ const state = await sdk.projects.getProjectState(project.id, hash);
44
+
45
+ if (state.syncRequired) {
46
+ await sdk.projects.initializeDeltaSync(project.id, hash);
47
+ }
48
+ }
43
49
  ```
44
50
 
45
51
  ## 📖 API Reference
@@ -75,7 +81,7 @@ interface CodeSolverSDKOptions {
75
81
 
76
82
  ### 📁 Projects API (`sdk.projects`)
77
83
 
78
- #### Управление проектами
84
+ #### 🏗️ Управление проектами
79
85
 
80
86
  ```typescript
81
87
  // Создание проекта
@@ -90,86 +96,54 @@ getProject(projectId: string): Promise<Project | null>
90
96
 
91
97
  // Поиск или создание проекта
92
98
  findOrCreateProject(projectPath: string, projectName: string, description?: string): Promise<Project>
93
-
94
- // Получение статуса индексации проекта
95
- getIndexingStatus(projectId: string): Promise<any>
96
- ```
97
-
98
- #### Примеры использования
99
-
100
- ```javascript
101
- // Создание нового проекта
102
- const project = await sdk.projects.createProject(
103
- 'My Web App',
104
- '/Users/dev/my-web-app',
105
- { description: 'React приложение' }
106
- );
107
-
108
- // Получение всех проектов пользователя
109
- const projects = await sdk.projects.getAllProjects();
110
- console.log(`У вас ${projects.length} проектов`);
111
-
112
- // Поиск существующего или создание нового
113
- const project = await sdk.projects.findOrCreateProject(
114
- '/path/to/project',
115
- 'My Project',
116
- 'Описание проекта'
117
- );
118
99
  ```
119
100
 
120
- ### 🚀 Indexing API (`sdk.indexing`)
121
-
122
- #### Управление индексацией
101
+ #### 📊 Управление состоянием и индексацией
123
102
 
124
103
  ```typescript
125
- // Создание проекта и запуск индексации
126
- indexProject(projectPath: string, projectName: string, description?: string): Promise<IndexProjectResult>
127
-
128
- // Получение статуса индексации
129
- getStatus(projectId: string): Promise<IndexingStatus>
130
-
131
- // ❌ ОТКЛЮЧЕН: waitForCompletion() - используйте WebSocket!
132
-
133
- // Отмена индексации
134
- cancelIndexing(projectId: string): Promise<void>
104
+ // Получение статуса индексации проекта
105
+ getIndexingStatus(projectId: string): Promise<any>
135
106
 
136
- // Перезапуск индексации
137
- restartIndexing(projectId: string): Promise<IndexingStatus>
107
+ // 🔍 Проверка состояния проекта (новое в v5.3.2+)
108
+ getProjectState(projectId: string, clientRootHash?: string): Promise<ProjectState>
109
+
110
+ // 🔄 Проверка прерванных сессий (новое в v5.5.0+)
111
+ getRecoveryStatus(projectId: string): Promise<{
112
+ hasInterruptedSession: boolean;
113
+ recoveryInfo?: RecoveryInfo;
114
+ }>
115
+
116
+ // 🔄 Возобновление прерванной синхронизации (новое в v5.5.0+)
117
+ resumeSync(projectId: string, options?: ResumeOptions): Promise<{
118
+ success: boolean;
119
+ message: string;
120
+ sessionId?: string;
121
+ continueFromBatch?: number;
122
+ resumeEndpoint?: string;
123
+ }>
124
+
125
+ // 🗑️ Отмена прерванной сессии (новое в v5.5.0+)
126
+ cancelRecovery(projectId: string): Promise<{
127
+ success: boolean;
128
+ message: string;
129
+ }>
138
130
  ```
139
131
 
140
- #### Типы данных
132
+ #### 🧹 Управление данными проекта
141
133
 
142
134
  ```typescript
143
- interface IndexingStatus {
144
- status: string; // 'pending' | 'processing' | 'completed' | 'failed'
145
- progress: number; // Прогресс 0-100
146
- totalFiles?: number; // Общее количество файлов
147
- processedFiles?: number; // Обработано файлов
148
- currentFile?: string; // Текущий обрабатываемый файл
149
- error?: string; // Сообщение об ошибке
150
- updatedAt?: string; // Время последнего обновления
151
- }
135
+ // 🧹 Очистка удаленных файлов (новое в v5.4.0+)
136
+ cleanupDeletedFiles(projectId: string, activeFiles: ActiveFile[]): Promise<FileCleanupResult>
137
+
138
+ // 🔍 Получение mapping обфусцированных путей (новое в v5.4.0+)
139
+ getFilePathMapping(projectId: string): Promise<{
140
+ success: boolean;
141
+ files: FilePathMapping[];
142
+ }>
152
143
  ```
153
144
 
154
- #### Примеры использования
155
145
 
156
- ```javascript
157
- // Запуск индексации
158
- const result = await sdk.indexing.indexProject(
159
- '/Users/dev/my-project',
160
- 'My Project'
161
- );
162
- console.log('Project ID:', result.projectId);
163
-
164
- // Получение статуса (единичный запрос)
165
- const status = await sdk.indexing.getStatus(result.projectId);
166
- console.log(`Прогресс: ${status.progress}%`);
167
-
168
- // ⚠️ ВАЖНО: Для real-time статуса используйте WebSocket!
169
- sdk.projectSync.on('sync-status-update', (status) => {
170
- console.log(`Статус обновлен: ${status.status}, прогресс: ${status.progress}%`);
171
- });
172
- ```
146
+
173
147
 
174
148
  ### 🔍 Search API (`sdk.search`)
175
149
 
@@ -310,6 +284,164 @@ sdk.projectSync.on('error', (error) => {
310
284
  sdk.disconnectWebSocket();
311
285
  ```
312
286
 
287
+ ---
288
+
289
+ ## 🎯 **ПОЛНОЕ РУКОВОДСТВО ПО УПРАВЛЕНИЮ ИНДЕКСАЦИЕЙ**
290
+
291
+ ### 🔄 **Cursor-like Workflow - Рекомендуемый подход**
292
+
293
+ ```typescript
294
+ import { CodeSolverSDK } from 'solver-sdk';
295
+
296
+ /**
297
+ * 🎯 ОСНОВНОЙ WORKFLOW - используйте этот паттерн в вашем VS Code расширении
298
+ */
299
+ async function handleProjectIndexing(projectPath: string) {
300
+ const sdk = new CodeSolverSDK({
301
+ baseURL: 'http://localhost:3000',
302
+ apiKey: 'your-api-key'
303
+ });
304
+
305
+ // 1. 🔍 Получить или создать проект
306
+ const project = await sdk.projects.findOrCreateProject(
307
+ projectPath,
308
+ path.basename(projectPath)
309
+ );
310
+ const projectId = project.id;
311
+
312
+ // 2. 🔄 КРИТИЧЕСКИ ВАЖНО: Проверить прерванные сессии
313
+ const recoveryStatus = await sdk.projects.getRecoveryStatus(projectId);
314
+
315
+ if (recoveryStatus.hasInterruptedSession) {
316
+ // 🎨 Cursor-like UX: Показать диалог восстановления
317
+ const info = recoveryStatus.recoveryInfo!;
318
+ const choice = await showUserChoice({
319
+ title: 'Indexing was interrupted',
320
+ message: `Indexing was interrupted at ${info.progress.percentage}%. Continue from where you left off?`,
321
+ buttons: [
322
+ { text: '🔄 Continue Indexing', value: 'continue' },
323
+ { text: '🆕 Start Fresh', value: 'fresh' }
324
+ ]
325
+ });
326
+
327
+ if (choice === 'continue') {
328
+ return await continueInterruptedIndexing(projectId);
329
+ } else {
330
+ return await startFreshIndexing(projectId);
331
+ }
332
+ }
333
+
334
+ // 3. 🔍 Проверить нужна ли синхронизация (Smart Sync)
335
+ const clientHash = await computeMerkleRootHash(projectPath);
336
+ const state = await sdk.projects.getProjectState(projectId, clientHash);
337
+
338
+ if (!state.syncRequired) {
339
+ console.log('✅ Проект актуален, синхронизация не нужна');
340
+ return { success: true, message: 'Project is up to date' };
341
+ }
342
+
343
+ // 4. 🚀 Начать новую синхронизацию
344
+ return await startFreshIndexing(projectId, clientHash);
345
+ }
346
+
347
+ /**
348
+ * 🔄 Продолжение прерванной индексации
349
+ */
350
+ async function continueInterruptedIndexing(projectId: string) {
351
+ const resumed = await sdk.projects.resumeSync(projectId, {
352
+ skipDuplicates: true,
353
+ continueFromLastBatch: true
354
+ });
355
+
356
+ if (!resumed.success) {
357
+ console.error('Failed to resume:', resumed.message);
358
+ return await startFreshIndexing(projectId); // Fallback
359
+ }
360
+
361
+ console.log(`✅ Resumed from batch ${resumed.continueFromBatch || 0}`);
362
+
363
+ // Продолжить обычную синхронизацию
364
+ const merkleHash = await computeMerkleRootHash(workspacePath);
365
+ return await performDeltaSync(projectId, merkleHash, {
366
+ resumeFromSession: resumed.sessionId
367
+ });
368
+ }
369
+
370
+ /**
371
+ * 🆕 Начать новую индексацию (с очисткой прерванных сессий)
372
+ */
373
+ async function startFreshIndexing(projectId: string, clientHash?: string) {
374
+ // Отменить прерванные сессии если есть
375
+ await sdk.projects.cancelRecovery(projectId);
376
+
377
+ // Вычислить hash если не передан
378
+ if (!clientHash) {
379
+ clientHash = await computeMerkleRootHash(workspacePath);
380
+ }
381
+
382
+ // Начать новую синхронизацию
383
+ return await performDeltaSync(projectId, clientHash);
384
+ }
385
+
386
+ /**
387
+ * 🧹 Полная очистка проекта (удаление всех данных)
388
+ */
389
+ async function clearProjectData(projectId: string) {
390
+ // ВНИМАНИЕ: Это удалит ВСЕ проиндексированные данные!
391
+
392
+ // Способ 1: Удалить проект полностью
393
+ await sdk.projects.deleteProject(projectId);
394
+ console.log('✅ Проект и все данные удалены полностью');
395
+
396
+ // Способ 2: Очистить только файлы (оставить проект)
397
+ const result = await sdk.cleanupDeletedFiles(projectId, []); // Пустой список = удалить все
398
+ console.log(`✅ Очищено: ${result.deletedFromQdrant} векторов, ${result.deletedFromPostgres} записей`);
399
+ }
400
+ ```
401
+
402
+ ### 📊 **Мониторинг прогресса индексации**
403
+
404
+ ```typescript
405
+ // Real-time мониторинг через WebSocket
406
+ await sdk.connectWebSocket();
407
+
408
+ sdk.projectSync.on('sync-progress', (progress) => {
409
+ updateProgressBar({
410
+ percentage: progress.progress,
411
+ stage: progress.stage,
412
+ currentFile: progress.currentChunk,
413
+ totalFiles: progress.totalChunks,
414
+ eta: calculateETA(progress)
415
+ });
416
+ });
417
+
418
+ sdk.projectSync.on('sync-completed', (result) => {
419
+ if (result.success) {
420
+ showSuccessMessage(`✅ Indexing completed: ${result.totalProcessed} files processed`);
421
+ } else {
422
+ showErrorMessage(`❌ Indexing failed: ${result.errors.join(', ')}`);
423
+ }
424
+ });
425
+
426
+ // Периодическая проверка статуса (альтернатива WebSocket)
427
+ const interval = setInterval(async () => {
428
+ const status = await sdk.projects.getDeltaSyncStatus(projectId);
429
+
430
+ updateProgressUI({
431
+ progress: status.progress,
432
+ chunksProcessed: status.chunksProcessed,
433
+ totalChunks: status.totalChunks,
434
+ errors: status.errors
435
+ });
436
+
437
+ if (status.status === 'completed' || status.status === 'failed') {
438
+ clearInterval(interval);
439
+ }
440
+ }, 2000);
441
+ ```
442
+
443
+ ---
444
+
313
445
  ### 🔄 Delta-Chunking API (`sdk.deltaSync`)
314
446
 
315
447
  #### Синхронизация с delta-chunking
@@ -421,6 +553,151 @@ for await (const chunk of stream) {
421
553
  }
422
554
  ```
423
555
 
556
+ ---
557
+
558
+ ## 🛠️ **УПРАВЛЕНИЕ ДАННЫМИ ПРОЕКТА**
559
+
560
+ ### 🧹 **Очистка и управление файлами**
561
+
562
+ ```typescript
563
+ /**
564
+ * 🧹 Очистка удаленных файлов (рекомендуется вызывать регулярно)
565
+ */
566
+ async function cleanupDeletedFiles(projectId: string, workspacePath: string) {
567
+ // Получить список активных файлов в workspace
568
+ const activeFiles = await getWorkspaceFiles(workspacePath);
569
+
570
+ // Очистить удаленные файлы из индекса
571
+ const result = await sdk.cleanupDeletedFiles(projectId, activeFiles.map(file => ({
572
+ filePath: file.path,
573
+ fileHash: file.hash,
574
+ lastModified: file.lastModified
575
+ })));
576
+
577
+ console.log(`🧹 Cleanup completed:`);
578
+ console.log(` - Removed from Qdrant: ${result.deletedFromQdrant} vectors`);
579
+ console.log(` - Removed from PostgreSQL: ${result.deletedFromPostgres} records`);
580
+ console.log(` - Active files: ${result.activeFiles}`);
581
+ }
582
+
583
+ /**
584
+ * 🔄 Управление индексацией проекта
585
+ */
586
+ async function manageProjectIndexing(projectId: string) {
587
+ // Вариант 1: Сбросить индексацию (проект остается)
588
+ const reset = await sdk.projects.resetIndexing(projectId);
589
+ console.log(`✅ Индексация сброшена: ${reset.clearedData.vectorsDeleted} векторов очищено`);
590
+
591
+ // Вариант 2: Перезапустить индексацию (сброс + подготовка)
592
+ const restart = await sdk.projects.restartIndexing(projectId);
593
+ if (restart.readyForNewSync) {
594
+ console.log('✅ Готов к новой индексации');
595
+ // Начать новую синхронизацию
596
+ const hash = await computeMerkleRootHash(workspacePath);
597
+ await sdk.projects.initializeDeltaSync(projectId, hash);
598
+ }
599
+
600
+ // Вариант 3: Очистить только удаленные файлы
601
+ const result = await sdk.cleanupDeletedFiles(projectId, []); // Пустой список = удалить все
602
+ console.log(`✅ Файлы очищены: ${result.deletedFromQdrant + result.deletedFromPostgres} записей`);
603
+
604
+ // Вариант 4: Удалить проект полностью
605
+ await sdk.projects.deleteProject(projectId);
606
+ console.log('✅ Проект полностью удален из системы');
607
+ }
608
+
609
+ /**
610
+ * 🔍 Диагностика состояния проекта
611
+ */
612
+ async function diagnoseProject(projectId: string) {
613
+ // Получить детальное состояние
614
+ const state = await sdk.projects.getProjectState(projectId);
615
+ console.log(`📊 Project State:`);
616
+ console.log(` - Name: ${state.projectName}`);
617
+ console.log(` - Total chunks: ${state.totalChunks}`);
618
+ console.log(` - Status: ${state.indexingStatus}`);
619
+ console.log(` - Last indexed: ${state.lastIndexedAt}`);
620
+ console.log(` - Merkle hash: ${state.merkleRootHash?.substring(0, 8)}...`);
621
+
622
+ // Проверить прерванные сессии
623
+ const recovery = await sdk.projects.getRecoveryStatus(projectId);
624
+ if (recovery.hasInterruptedSession) {
625
+ const info = recovery.recoveryInfo!;
626
+ console.log(`⚠️ Interrupted session found:`);
627
+ console.log(` - Progress: ${info.progress.percentage}% (${info.progress.processed}/${info.progress.total})`);
628
+ console.log(` - Interrupted: ${info.interruptedAt}`);
629
+ console.log(` - Can resume: ${info.canResume}`);
630
+ console.log(` - Reason: ${info.resumeReason}`);
631
+ }
632
+
633
+ // Получить file mapping для отладки
634
+ const mapping = await sdk.projects.getFilePathMapping(projectId);
635
+ console.log(`📁 File mapping: ${mapping.files.length} files indexed`);
636
+ }
637
+ ```
638
+
639
+ ### ⚠️ **Troubleshooting и восстановление**
640
+
641
+ ```typescript
642
+ /**
643
+ * 🚨 Экстренное восстановление при проблемах
644
+ */
645
+ async function emergencyRecovery(projectId: string) {
646
+ try {
647
+ console.log('🚨 Starting emergency recovery...');
648
+
649
+ // 1. Проверить состояние проекта
650
+ const state = await sdk.projects.getProjectState(projectId);
651
+ console.log(`Current state: ${state.indexingStatus}`);
652
+
653
+ // 2. Отменить все прерванные сессии
654
+ const cancelled = await sdk.projects.cancelRecovery(projectId);
655
+ if (cancelled.success) {
656
+ console.log('✅ Cancelled interrupted sessions');
657
+ }
658
+
659
+ // 3. Очистить поврежденные данные (если нужно)
660
+ const cleaned = await sdk.cleanupDeletedFiles(projectId, []);
661
+ console.log(`🧹 Cleaned ${cleaned.deletedFromQdrant + cleaned.deletedFromPostgres} corrupted records`);
662
+
663
+ // 4. Начать полную ресинхронизацию
664
+ const merkleHash = await computeMerkleRootHash(workspacePath);
665
+ await sdk.projects.initializeDeltaSync(projectId, merkleHash);
666
+
667
+ console.log('✅ Emergency recovery completed, full resync started');
668
+
669
+ } catch (error) {
670
+ console.error('❌ Emergency recovery failed:', error);
671
+
672
+ // Последний шанс: удалить и пересоздать проект
673
+ await sdk.projects.deleteProject(projectId);
674
+ const newProject = await sdk.projects.createProject(projectName, projectPath);
675
+ console.log(`🆕 Created new project: ${newProject.id}`);
676
+ }
677
+ }
678
+
679
+ /**
680
+ * 🔄 Принудительное возобновление (для сложных случаев)
681
+ */
682
+ async function forceResumeSync(projectId: string) {
683
+ const resumed = await sdk.projects.resumeSync(projectId, {
684
+ forceResume: true, // Игнорировать canResume=false
685
+ skipDuplicates: true, // Пропустить дубликаты
686
+ continueFromLastBatch: false // Начать сначала, но с сохраненным прогрессом
687
+ });
688
+
689
+ if (resumed.success) {
690
+ console.log('✅ Force resume successful');
691
+ return resumed;
692
+ } else {
693
+ console.error('❌ Force resume failed, falling back to fresh sync');
694
+ return await startFreshIndexing(projectId);
695
+ }
696
+ }
697
+ ```
698
+
699
+ ---
700
+
424
701
  ## 💡 Рекомендации по использованию
425
702
 
426
703
  ### Real-time уведомления
@@ -584,6 +861,107 @@ sdk.projectSync.on('sync-status-update', (status) => {
584
861
  - 🔄 Delta-chunking для эффективной синхронизации
585
862
  - 🛡️ Автоматическая обработка лимитов сервера
586
863
 
864
+ ---
865
+
866
+ ## 📋 **QUICK REFERENCE - Управление индексацией**
867
+
868
+ ### 🔄 **Основные методы (обязательные для VS Code расширения)**
869
+
870
+ | Метод | Описание | Когда использовать |
871
+ |-------|----------|-------------------|
872
+ | `getRecoveryStatus(projectId)` | Проверка прерванных сессий | При открытии проекта |
873
+ | `getProjectState(projectId, hash?)` | Проверка актуальности | Перед синхронизацией |
874
+ | `resumeSync(projectId, options?)` | Продолжить прерванную синхронизацию | Кнопка "Continue" |
875
+ | `cancelRecovery(projectId)` | Отменить прерванную сессию | Кнопка "Start Fresh" |
876
+ | `initializeDeltaSync(projectId, hash)` | Начать новую синхронизацию | Новая индексация |
877
+ | `finalizeDeltaSync(projectId)` | Завершить синхронизацию | После отправки всех батчей |
878
+ | `cleanupDeletedFiles(projectId, files)` | Очистить удаленные файлы | При изменении файлов |
879
+ | `resetIndexing(projectId)` | **Сброс индексации** | Очистить данные, сохранить проект |
880
+ | `restartIndexing(projectId)` | **Перезапуск индексации** | Сброс + подготовка к новой |
881
+ | `deleteProject(projectId)` | **Полное удаление проекта** | Удалить проект и все данные |
882
+
883
+ ### 🎯 **Полный список методов управления индексацией**
884
+
885
+ ```typescript
886
+ // 🔍 ПРОВЕРКА СОСТОЯНИЯ
887
+ await sdk.projects.getProjectState(projectId, clientHash) // Нужна ли синхронизация?
888
+ await sdk.projects.getRecoveryStatus(projectId) // Есть ли прерванные сессии?
889
+ await sdk.projects.getDeltaSyncStatus(projectId) // Текущий статус синхронизации
890
+
891
+ // 🚀 УПРАВЛЕНИЕ СИНХРОНИЗАЦИЕЙ
892
+ await sdk.projects.initializeDeltaSync(projectId, hash) // Начать новую синхронизацию
893
+ await sdk.projects.resumeSync(projectId, options) // Продолжить прерванную
894
+ await sdk.projects.finalizeDeltaSync(projectId) // Завершить синхронизацию
895
+ await sdk.projects.cancelDeltaSync(projectId) // Отменить активную синхронизацию
896
+
897
+ // 🔄 УПРАВЛЕНИЕ ПРЕРЫВАНИЯМИ
898
+ await sdk.projects.cancelRecovery(projectId) // Отменить восстановление
899
+
900
+ // 🧹 УПРАВЛЕНИЕ ДАННЫМИ
901
+ await sdk.cleanupDeletedFiles(projectId, activeFiles) // Очистить удаленные файлы
902
+ await sdk.projects.getFilePathMapping(projectId) // Получить mapping файлов
903
+ await sdk.projects.resetIndexing(projectId) // Сброс индексации (проект остается)
904
+ await sdk.projects.restartIndexing(projectId) // Перезапуск индексации
905
+ await sdk.projects.deleteProject(projectId) // ПОЛНОЕ удаление проекта
906
+
907
+ // 📊 МОНИТОРИНГ (WebSocket)
908
+ sdk.projectSync.on('sync-progress', callback) // Real-time прогресс
909
+ sdk.projectSync.on('sync-completed', callback) // Завершение синхронизации
910
+ sdk.projectSync.on('sync-status-update', callback) // Обновления статуса
911
+ ```
912
+
913
+ ### 🎯 **Cursor-like UX Pattern**
914
+
915
+ ```typescript
916
+ // Главный workflow для VS Code расширения
917
+ async function openProject(projectPath: string) {
918
+ // 1. Создать/найти проект
919
+ const project = await sdk.projects.findOrCreateProject(projectPath, projectName);
920
+
921
+ // 2. Проверить прерванные сессии
922
+ const recovery = await sdk.projects.getRecoveryStatus(project.id);
923
+
924
+ if (recovery.hasInterruptedSession) {
925
+ // Показать диалог: "Continue indexing (67%)" или "Start fresh"
926
+ const choice = await vscode.window.showInformationMessage(
927
+ `Indexing was interrupted at ${recovery.recoveryInfo.progress.percentage}%. Continue?`,
928
+ 'Continue', 'Start Fresh'
929
+ );
930
+
931
+ if (choice === 'Continue') {
932
+ await sdk.projects.resumeSync(project.id);
933
+ } else {
934
+ await sdk.projects.cancelRecovery(project.id);
935
+ }
936
+ }
937
+
938
+ // 3. Проверить нужна ли синхронизация
939
+ const hash = await computeMerkleRootHash(projectPath);
940
+ const state = await sdk.projects.getProjectState(project.id, hash);
941
+
942
+ if (state.syncRequired) {
943
+ await sdk.projects.initializeDeltaSync(project.id, hash);
944
+ }
945
+ }
946
+ ```
947
+
948
+ ### 🚨 **Error Handling Best Practices**
949
+
950
+ ```typescript
951
+ // Обработка всех возможных ошибок
952
+ try {
953
+ await performDeltaSync(projectId, merkleHash);
954
+ await sdk.projects.finalizeDeltaSync(projectId); // ОБЯЗАТЕЛЬНО!
955
+ } catch (error) {
956
+ console.error('Sync failed:', error);
957
+
958
+ // Система автоматически пометит сессию для восстановления
959
+ // При следующем открытии пользователь увидит "Continue indexing"
960
+ }
961
+ ```
962
+
963
+ ---
964
+
587
965
  ## 📞 Поддержка
588
966
 
589
967
  - **GitHub**: [Issues](https://github.com/codesolver/solver-sdk/issues)
@@ -596,4 +974,17 @@ MIT License - см. [LICENSE](LICENSE) файл.
596
974
 
597
975
  ---
598
976
 
599
- **🚀 Code Solver SDK v5.2.0** - Создано с ❤️ для разработчиков
977
+ **🚀 Code Solver SDK v5.6.0** - Создано с ❤️ для разработчиков
978
+
979
+ ### 🎯 **НОВОЕ В v5.6.0: Advanced Indexing Management**
980
+ - 🔄 **resetIndexing()** - сброс индексации (проект остается)
981
+ - 🚀 **restartIndexing()** - перезапуск индексации + подготовка
982
+ - 🎯 **Гибкий контроль** - точное управление без удаления проекта
983
+ - 📖 **Enhanced UX** - готовые паттерны для VS Code
984
+
985
+ ### 🎯 **v5.5.0: Resilient Sync System**
986
+ - 🔄 **Cursor-like Recovery** - восстановление прерванных сессий
987
+ - 📊 **Детальный прогресс** - процент завершения и ETA
988
+ - 🛡️ **Автоматическая обработка прерываний** - сеть, падения, ошибки
989
+ - 🧹 **Smart Cleanup** - точная очистка удаленных файлов
990
+ - 🎨 **Production UX** - готовые паттерны для VS Code расширений