83 lines
No EOL
12 KiB
Markdown
83 lines
No EOL
12 KiB
Markdown
## Кодер 1
|
||
|
||
### Реализованный Scope
|
||
1. **Scope 1 (DATA-07 - Lightweight Session List Projection)**:
|
||
- В [Entities.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/core/storage/Entities.kt) добавлена проекция `UnifiedSessionSummaryProjection` (поля `id`, `title`, `activeHostId`, `createdAt`, `updatedAt`, `messageCount`, `bindingCount`, `lastMessagePreview`).
|
||
- В [Daos.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/core/storage/Daos.kt) и [FakeDaos.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/test/java/app/hermes/mobile/core/storage/FakeDaos.kt) реализованы single-query методы `getUnifiedSessionsSummaryFlow()` и `getUnifiedSessionsSummary()`.
|
||
- В [UnifiedSessionRepository.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/core/repository/UnifiedSessionRepository.kt) поток `sessions` переведён на `sessionDao.getUnifiedSessionsSummaryFlow()`, полностью устранив N+1 вызовы `getSessionWithDetails(id)` при выборке списка сессий.
|
||
- В [MultiHostModels.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/core/model/MultiHostModels.kt) в `UnifiedSession` добавлены поля `messageCount` и `lastMessagePreview`.
|
||
- В [UnifiedSessionsScreen.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/feature/unified_sessions/UnifiedSessionsScreen.kt) карточка сессии отображает `messageCount` из проекции.
|
||
|
||
2. **Scope 2 (DATA-09 - Cache Eviction & Memory Bounding)**:
|
||
- В [UnifiedSessionRepository.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/core/repository/UnifiedSessionRepository.kt) реализован метод `releaseSession(sessionId)`, очищающий состояние сессии (`sessionMessagesState`, `sessionExecutingState`, `sessionApprovalsState`, `sessionClarifyQueueState`, `sessionActiveClarifyFlows`, `hostExecutingState`, `sessionHostMutexes`, `toolToMessageMap`).
|
||
- Добавлен механизм `pruneIdleSessionCaches()` с лимитом `MAX_CACHED_SESSIONS = 10`, предотвращающий неограниченный рост кэшей при навигации по десяткам сессий.
|
||
- В [ChatViewModel.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/feature/chat/ChatViewModel.kt) переопределён метод `onCleared()` с вызовом `sessionRepo.releaseSession(sessionId)`.
|
||
|
||
3. **Scope 3 (DATA-10 - Strict Tool and Thinking Attribution)**:
|
||
- В [UnifiedSessionRepository.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/core/repository/UnifiedSessionRepository.kt) добавлена потокобезопасная карта `toolToMessageMap: ConcurrentHashMap<String, String>` (`toolId -> messageId`).
|
||
- Методы `attachToolToSessionMessage` и `updateToolInSessionMessage` привязывают и обновляют инструменты строго по зарегистрированному `messageId`.
|
||
- Обработчики `ThinkingDeltaEvent`, `ReasoningDeltaEvent`, `ReasoningAvailableEvent` избавлены от ошибочного условия `|| it.role == MessageRole.ASSISTANT` и осуществляют поиск строго по `event.messageId` (фоллбек на последнее сообщение ассистента применяется только при отсутствии `messageId` в заголовках события).
|
||
- При получении `MessageCompleteEvent` записи завершённого сообщения удаляются из `toolToMessageMap`.
|
||
|
||
4. **Scope 4 (UI-07 - Smooth Non-Thrashing Auto-Scroll)**:
|
||
- В [ChatScreen.kt](file:///e:/Agent%20projects/hermes-android-apk/app/src/main/java/app/hermes/mobile/feature/chat/ChatScreen.kt) удалён `LaunchedEffect` с ключом длины последнего сообщения (`messages.lastOrNull()?.content?.length`).
|
||
- Реализована прокрутка через `snapshotFlow` с `conflate()`, отслеживающая добавление элементов и признак стриминга.
|
||
- Целевой индекс скорректирован на валидный `maxOf(0, totalItems - 1)`.
|
||
- Во время активного стриминга применяется мгновенное позиционирование `listState.scrollToItem` вместо конфликтующих анимаций.
|
||
- Если пользователь прокрутил историю вверх (`listState.canScrollForward == true`), автопрокрутка не срывает позицию чтения.
|
||
|
||
---
|
||
|
||
## Замеры до/после
|
||
|
||
| Метрика | До (Base SHA `ab1e5cb`) | После (Round 1) | Подтверждение |
|
||
|---|---|---|---|
|
||
| **SQL-запросы при открытии списка из 100 сессий** | **101 запрос** (1 + 100 `getSessionWithDetails`) | **1 запрос** (Single projection O(1)) | `SessionListQueryCountTest` |
|
||
| **Удерживаемое состояние в кэше после 50 сессий** | **50 сессий / 100% утечка** (`messagesCache=50`, `sessionExec=50`, `hostExec=50`, `mutexes=50`) | **0 сессий** (при `releaseSession`) / макс. **<= 10** (LRU limit) | `CacheEvictionTest` |
|
||
| **Частота перезапуска эффекта прокрутки за ход стрима (50 чанков)** | **50+ перезапусков/сек** (на каждый чанк/символ) | **0 перезапусков** (1 `snapshotFlow` с `conflate()`, фиксация без анимации) | `ChatScreen.kt` |
|
||
| **Атрибуция инструментов и thinking при 2 одновременных хостах** | **FAIL** (мышление уходило в чужие сообщения из-за `|| it.role == ASSISTANT`, инструменты теряли `messageId`) | **PASS** (100% строгая изоляция по `hostId` и `messageId`) | `ToolAttributionTest` |
|
||
|
||
---
|
||
|
||
### Проверенные команды
|
||
- `./gradlew.bat --no-daemon testDebugUnitTest`: **130/130 tests passed (0 failures)**. Exit code: `0`.
|
||
- `./gradlew.bat --no-daemon lint`: **0 errors, 0 warnings**. Exit code: `0`.
|
||
- `./gradlew.bat --no-daemon assembleDebug`: **BUILD SUCCESSFUL**. Exit code: `0`.
|
||
|
||
### Изменённые файлы
|
||
- `app/src/main/java/app/hermes/mobile/core/model/MultiHostModels.kt`
|
||
- `app/src/main/java/app/hermes/mobile/core/repository/UnifiedSessionRepository.kt`
|
||
- `app/src/main/java/app/hermes/mobile/core/storage/Daos.kt`
|
||
- `app/src/main/java/app/hermes/mobile/core/storage/Entities.kt`
|
||
- `app/src/main/java/app/hermes/mobile/feature/chat/ChatScreen.kt`
|
||
- `app/src/main/java/app/hermes/mobile/feature/chat/ChatViewModel.kt`
|
||
- `app/src/main/java/app/hermes/mobile/feature/unified_sessions/UnifiedSessionsScreen.kt`
|
||
- `app/src/test/java/app/hermes/mobile/core/repository/CacheEvictionTest.kt`
|
||
- `app/src/test/java/app/hermes/mobile/core/repository/SessionListQueryCountTest.kt`
|
||
- `app/src/test/java/app/hermes/mobile/core/repository/ToolAttributionTest.kt`
|
||
- `app/src/test/java/app/hermes/mobile/core/storage/FakeDaos.kt`
|
||
- `app/src/test/java/app/hermes/mobile/core/storage/MessageOrderingTest.kt`
|
||
# |