CACHE.md + требования: кэш сообщений на клиенте, десктоп как эталон для Android

This commit is contained in:
Porfiry
2026-09-19 04:45:43 +03:00
parent 57e7fe1d17
commit d5f4c67779
3 changed files with 251 additions and 0 deletions
+67
View File
@@ -154,6 +154,70 @@
- **R29.** Развёрнутый вид — подробности шага: аргументы, результат, время.
- **R30.** Сворачивание и разворачивание — по нажатию на строку.
## 8. Простота кода и кэш сообщений
### 8.1. Цель: клиент должен читаться
- **R31.** **Главная цель — чтобы клиент был максимально прост по коду.** Я должен
открыть исходники и понять, что там происходит. Это важнее, чем сэкономить
строки или вынести лишнее.
- **R31.1.** **Сначала десктоп, затем Android по тем же лекалам.** Десктопный клиент
— образец. Когда он получится удобным и понятным, Android делается по его
решениям. Поэтому простота кода здесь — не пожелание, а условие.
- **R32.** Распознавание голоса, микрофон и детекция речи — **готовые библиотеки**,
свои (`mic-kmp`, `asr-kmp`, `vad-kmp`). Писать заново ничего не надо, и это уже
не «вынос в отдельное место» — библиотеки и есть отдельное место.
- **R33.** Материал найден, разобран: `MIC-ASR-SEARCH.md`. Там же сказано, почему
код микрофона из `ai/assistent` брать **не** надо.
- **R34.** Из `ai/assistent` берём только приёмы отрисовки, плагины и версии —
не архитектуру, не экраны, не дизайн. Разбор: `BORROW-FROM-ASSISTENT.md`.
### 8.2. Кэш сообщений на клиенте — решение принято
**Задача:** не тянуть всю историю диалога заново при каждом открытии окна.
**Схема:**
1. Открыли диалог — смотрим свой кэш.
2. Берём из кэша **последнее сообщение** и его дату.
3. Спрашиваем библиотеку `client`: есть ли сообщения **новее** этой даты.
4. Были — забираем только новые, добавляем в кэш, рисуем.
5. Не были — ничего не делаем.
- **R35.** **Это работает: в библиотеке `client` всё нужное есть.** Функция
`Conversation.getMessages(after, offset, limit)` отдаёт сообщения **строго новее**
указанной даты (проверено: в отборе `created_at > ?`). Пустой ответ = после
нашего сообщения ничего не появилось. Есть и версия потоком, страницами по 100
(`PAGE_SIZE = 100`). Отдельно создавать диалог для проверки не нужно — только
если открываем новый.
- **R36.** **Дубли отсекаются по `id` сообщения.** Идентификатор один и тот же
и в живом потоке, и в истории (`Message.id`). То есть при догрузке не нужно
угадывать, что уже нарисовано — сверяем по идентификатору.
- **R37.** **Самого кэша в библиотеке нет** — это пишем мы. Библиотека даёт только
«спроси, что новее».
**Три места, где схема может порваться (найдено в коде, не предположения):**
- **R38.** **Одинаковые даты.** Отбор строго «новее» (`created_at > ?`), поэтому
если два сообщения получили **ровно одну и ту же дату** — второе в ответ не
попадёт. Порядок внутри одной даты сервер задаёт сам (сортировка по времени,
затем по `id`). Реальный риск невелик (дата с точностью до миллисекунд), но
при сверке по `id` (R36) он не страшен вовсе.
- **R39.** **Прерванный ответ в историю не попадает.** Если ответ прервали кнопкой
«Стоп», кусок ответа остаётся только в живом потоке, в историю он не пишется
(`Event.Interrupted`). В кэше окажется то, чего на сервере нет.
- **R40.** **Живой поток тоже надо просить «с этого момента».** У подписки на события
есть тот же параметр «после»; без него после переподключения пропустим события.
- **R41.** **Решение:** кэш делаем. Схема — из R35. Где хранится (файл или лёгкая
база) — **не решено**, см. раздел 9.
### 8.3. Что не выносим
- **R42.** Экраны, пузырь сообщения, хранение списка агентов — **остаются в клиенте**.
Это и есть клиент, выносить их некуда.
- **R43.** Полезный признак, что что-то не вынесено: **в экране накопилась логика
длиннее пары десятков строк.** Значит, это место жить в экране не должно.
## 9. Решения, которые ещё не приняты
- Запись: по нажатию или на удержание.
@@ -162,6 +226,9 @@
- Нужен ли картинке размер/форма — показывать кружком без изменений или обрезать.
- Где хранится список агентов — в файле на диске или спрашивать сервер.
- Как выглядит показ хода работы агента в свёрнутом виде.
- **Где хранится кэш сообщений** — обычный файл на диске или лёгкая база (R41).
- Сколько держать в кэше и когда чистить (старые диалоги).
- Что делать с куском прерванного ответа в кэше (R39): хранить или выбрасывать.
## 10. Как проверяем