subochev
032424f513
Mercury: enable heartbeat on connect (keeps link alive), autolock endpoint
2026-08-25 01:15:00 +03:00
subochev
4556d3b6e4
Mercury: verify handshake echo, autolock endpoint, ringInfo-safe status
2026-08-25 00:54:31 +03:00
subochev
b40e44c653
DebugHttpServer: Mercury BLE-эндпоинты (/mercury/status|connect|disconnect|screen/off|screen/on)
2026-08-24 23:24:07 +03:00
subochev
d674b31a81
Внедрение rayneo-mercury: зависимость + MercuryPanel (BLE-тест: погасить/включить экран)
2026-08-24 23:19:37 +03:00
subochev
c222a4ac76
stt(phone): полный текст по клику — whisper на всём буфере, VAD только для промежуточных фраз
2026-08-24 22:11:08 +03:00
subochev
e21c27b0ee
stt(dump): WAV-заголовок — размеры little-endian (плееры открывают дампы)
2026-08-24 21:36:53 +03:00
subochev
0d79b5aa33
stt(mic): усиление микрофона очков ×10 — VAD/Whisper видят речь (пустая фраза)
2026-08-24 20:57:06 +03:00
subochev
40edd88c1d
stt(mic): вынести кадровую арифметику в micChunkBytes + регрессионные тесты MicChunkTest
...
- CHUNK_BYTES=3200, micChunkBytes(buf, frames): кадры read() -> байты (*2)
- 4 теста: полный чанк 3200 Б без копирования, короткий read,
документация старого бага (copyOf(кадры) = полка), inFrameCount=1600
2026-08-24 12:23:33 +03:00
subochev
fc84ba16b6
stt(mic): request frames in frames (inFrameCount), not bytes — each chunk now carries full 100 ms
2026-08-24 11:10:05 +03:00
subochev
c940a7e0eb
stt(mic): AudioRecord.read возвращает КАДРЫ, а не байты — не терять вторую половину каждого 100-мс чанка (впечатление 'пропускает через один')
2026-08-24 11:08:27 +03:00
subochev
22eb83fd17
stt: debug-дампы аудио-пути (очки: сырой микрофон в WAV; телефон: принятые PCM) по старту от stt_dump.marker
2026-08-24 05:58:59 +03:00
subochev
c1c169036a
stt: VAD-интерфейс (Sherpa боевая / Silero тестовая), PhraseRecognizer (Whisper), чистый full-text-тест на реальном Silero VAD
2026-08-24 05:43:29 +03:00
subochev
7557d7229f
Очки: отмена слушания двойным тапом — SttCancel reason=cancel
2026-08-24 03:01:55 +03:00
subochev
504e66f0c6
Очки: красный индикатор записи микрофона в режиме «слушаю»
2026-08-23 21:58:36 +03:00
subochev
e24caaa684
Очки: разграничение SttCancel (user/timeout) — выход из режима при тишине 30с, микрофон закрывается при потере фокуса
2026-08-23 21:17:43 +03:00
subochev
eaca47c443
Очки: единый скролл диалога на оба глаза + мгновенная пауза звука телефона при вызове ассистента
2026-08-23 21:08:40 +03:00
subochev
706cc10d1e
Очки: история диалога в свайпе + распознавание в LLM только по клику (касяки 1-3)
2026-08-23 20:15:21 +03:00
subochev
51049d56a8
Чат: автоименование сессии из первого сообщения
...
- Assistant.processInSession: безымянная сессия получает имя из
первого сообщения (обреза 30 симв.), «беседка» — пустое
- ChatScreen: периодическая перезагрузка подхватывает и список
сессий — шапка обновляет название без ручного переключения
2026-08-23 17:40:12 +03:00
subochev
ce2d9c5448
Чат: клавиатура не вырезает верх окна (adjustResize + imePadding)
...
- MainActivity: windowSoftInputMode=adjustResize — окно сжимается,
а не панорамируется вверх при появлении IME
- ChatScreen: Modifier.imePadding() — контент честно ужимается
под высоту клавиатуры
2026-08-23 17:30:40 +03:00
subochev
d585ddf576
Локальная LLM: конфиг автора + uses-native-library в <application>
...
- AndroidManifest: три uses-native-library (libOpenCL/libvndksupport/libcdsprpc)
ВНУТРИ <application> — aapt2 8.9.2 отбрасывает тег на уровне <manifest>
- LocalLlm: enableSpeculativeDecoding=true, GPU/GPU/CPU бэкенды (как у автора)
- DebugHttpServer: HTTP-отладка ассистента без UI
- Log/PhoneApp: мелкие правки
Подтверждено: движок поднимается, локальный чат отвечает на HONOR AXGL024B05001337
2026-08-23 17:25:55 +03:00
subochev
75496dd35d
Фикс локальной LLM: таймаут 300с для LOCAL (инициализация движка ~17с + генерация), CPU-бэкенд без спекуляции (MTP виснет на CPU, GPU-делегат падает), диагностика chat()
...
Проверено на железе (HONOR FCP-N49): Gemma 4 E2B отвечает
«Здравствуйте! Чем я могу вам помочь с вашими очками Viewmate?»
(15 чанков, 61 символ, ~19с генерации).
2026-08-23 04:38:02 +03:00
subochev
7527cf8848
LLM: интерфейс + две реализации (Qwen удалённо / Gemma 4 E2B локально) + переключатель
...
- LlmClient интерфейс; RemoteLlmClient (OkHttp, llm.binom.pw) и LocalLlmClient (LiteRT-LM, Gemma 4 E2B)
- LocalLlm: Gemma4E2B (SHA-256, GPU/CPU-бэкенды), buildLocalLlmPrompt (SYSTEM→systemInstruction, TOOL→user), GemmaModelDownloader (стриминг, прогресс, фолбэк источников), спекулятивное декодирование
- LlmPrefs (персистентность выбора), PhoneApp: фабрика по llmChoice, пересоздание ассистента, скачивание/отмена
- UI: GlassesInfoScreen — выбор сервер/локальная + прогресс; ChatScreen — индикатор активной модели
- Тесты: +12 (LlmLocalTest) — phone 154 зелёных
2026-08-23 02:52:22 +03:00
subochev
2d6ca1e097
План: локальная модель на телефоне (Gemma 4 E2B, LiteRT LM) — в очереди, ждёт отмашки
...
- Источник: vayun-mathur/Modern-Apps openassistant (клон ~/WORK/modern-apps/)
- Интерфейс LLM + 2 реализации: Qwen3.8 (сеть) и Gemma E2B (локально, оффлайн)
- Разбор скорости: GPU-бэкенд + MTP-спекулятивный декодинг, 20-35 ток/с на 8 Gen 3
- Реализация НЕ начата — по правилу пользователя «без отмашки не начинай»
2026-08-23 02:00:21 +03:00
subochev
f75e672819
Очки: жесты и режимы общения с ассистентом (по docs/gestures-and-modes.md)
...
- AssistantMode: NONE/LISTENING/THINKING/ANSWER + чистая gestureDecision (матрица жестов)
- Клик в «ответ виден» = новая фраза; DoubleClick = выход (кино на паузе); свайпы = скролл
- Плавный скролл ответа: SlideContinuous delta → answerScrollDelta → scrollOffset (зажим 0..max)
- Индикатор «думаю...» (thinking, сброс на ShowText)
- AssistantOverlay: затемнение 72%, по глазам, скролл-аккумулятор
- Тесты: 22 (AssistantGesturesTest) — glasses 91 зелёных
2026-08-23 01:55:24 +03:00
subochev
f36d04adc1
Доки: жесты и режимы общения с ассистентом (design) + TASK
2026-08-23 01:08:38 +03:00
subochev
28d0f9b68d
Агент: медиа-тулсет (search/info/play) на Jellyfin + скилл media
...
- MEDIA_TOOLSET + MediaToolExecutor: search (поиск с лимитом), info (детали), play (проверки+запуск)
- JellyfinMediaSource: обёртка JellyfinClient (search/item) с защитой userId
- agentPlayMedia: проверки (очки на связи, видео скачано на очки, звук на телефоне) → watch с позицией
- PhoneActions.watch(startPositionMs), JellyfinItem.ProductionYear
- скилл app-phone/skills/media.md (frontmatter: name/description)
- MediaToolsTest: 22 кейса — всего 142 теста зелёные
2026-08-22 21:42:53 +03:00
subochev
c5cbc893ac
Агент: механика скиллов и тулсетов (ядро 5 тул, подмена, невидимые enable/disable)
...
По ТЗ TASK-agent-tools.md:
- Skills/SkillRepository/SkillRegistry: frontmatter-скиллы из files/skills, индекс для промпта, ленивое read_skill
- Toolsets/ToolsetRegistry: активность на сессию в хиппе, таймаут 10 мин (инжект часов), префиксная маршрутизация, идемпотентные enable/disable
- AgentToolkit: сборка промпта (3 состояния), диспач, бесшовная подмена вызова на активацию, валидация аргументов
- Assistant: цикл тулов с невидимыми вызовами (MAX_LLM_CALLS=8, MAX_TOOL_CALLS=3)
- Тесты: 18 новых (AgentToolkitTest 17 + SkillsTest 6 + ToolsetRegistryTest 9) — всего 120, зелёные
2026-08-22 21:13:29 +03:00
subochev
22369670cb
ТЗ: агент — скиллы + тулсеты (TASK-agent-tools.md)
...
Архитектура (договорено 2026-08-22):
- скиллы (знания) ≠ тулсеты (руки)
- ядро 5 тул: время, show_text, read_skill, enable/disable_toolset
- префиксы тул по набору (media_*)
- активность на сессию, в хиппе, таймаут 10 мин
- enable/disable невидимы (не в истории), скилл исчезает при активном наборе
- бесшовная подмена вызова на активацию
- история не вычищается
2026-08-22 20:15:48 +03:00
subochev
bbf7a020d4
Ассистент Порфирий: тула времени, сессии, чат-UI, голосовой цикл; BT-транспорт очки↔телефон
...
- BT (RFCOMM SPP 00001105) вместо WiFi: BtGlassesTransport/BtServerTransport, реконнект 3с
- PlaybackService (foreground, WAKE_LOCK) против морозов HONOR
- Ассистент: AgentTools (TimeTool ISO 8601), TOOL_CALL-протокол, сессии SQLite (UUID)
- Чат-UI: создание/сброс/переключение сессий, автообновление ленты 2с
- LlmClient на прямом OkHttp (Koog давал пустой content на длинных историях)
- Голосовой цикл: тройной тап на очках → STT → активная сессия → ShowText
- Тесты: AgentToolsTest (3), GlassesServerTest переписан (6) — зелёные
2026-08-22 16:31:04 +03:00
subochev
adfe376dd4
CI: системный JDK 17 на раннере вместо setup-java (adoptium виснет)
build / Android APK to F-Droid (release) Successful in 1m2s
1
2026-08-21 19:45:43 +03:00
subochev
20654e916e
CI: Java 17 (jvmToolchain в lib-core)
build / Android APK to F-Droid (release) Failing after 14m32s
2026-08-21 19:31:37 +03:00
subochev
ee9700c558
CICD: сборка APK на release → F-Droid; versionCode из тега; фикс скролла каталога и масштаба
build / Android APK to F-Droid (release) Failing after 36s
2026-08-21 19:27:02 +03:00
subochev
ee86b9dc50
Revert "feat: retry конвертации (2 попытки) при failed/error"
...
This reverts commit cbcd22f09c .
2026-08-21 12:08:57 +03:00
Hermes Agent
cbcd22f09c
feat: retry конвертации (2 попытки) при failed/error
...
- polling-цикл: при status failed/error — retry (до 2 раз)
- логирование каждого retry
- после исчерпания retry — текущее поведение (кнопка 'Перезаказать')
2026-08-21 11:54:48 +03:00
Hermes Agent
a434d5bb12
feat: потоковый локальный ассистент — фраза → LLM → ответ на очки
...
- agent/Assistant.kt: оркестратор диалога (SQLite-история + Koog), таймаут 30с,
сессия одна живая, история — последние 20 сообщений
- ChatDao.latestSessionId(); SYSTEM_PROMPT нейтральный (TODO: персона)
- PhoneApp: очередь фраз (Channel UNLIMITED), assistantLoop (THINKING/ShowText/IDLE),
ensureAssistant ленивый; ключ/модель из BuildConfig (local.properties)
- Очки: assistantText StateFlow, ShowText → оверлей (белый текст речи + серый ответ),
оверлей остаётся после Click до новой сессии
- AssistantTest (androidTest, 3 теста: сессия/история/таймаут) — OK (6 tests всего)
- README: строка про ассистента
2026-08-20 12:35:49 +03:00
Hermes Agent
d9d34e9277
feat: история общения (SQLite) + Koog LLM-клиент в app-phone
...
SQLite (голый SQLiteOpenHelper, без ORM — как решили):
- sessions (id, title, created_at, updated_at) + messages (role, content,
tool_call_id, tool_calls JSON, attachments JSON, created_at) по утверждённой
схеме; FK-каскад; CHECK на роли.
- ChatDb + ChatDao (createSession/listSessions/rename/touch/delete, addMessage,
messagesForSession), доступ через PhoneApp.chatDao.
- Unit: ModelsTest (роли, JSON tool_calls/attachments). androidTest:
ChatDaoTest — CRUD-круг + каскад — OK (3 tests) на эмуляторе.
Koog (JetBrains) — базовый LLM-клиент, без агентного слоя:
- ai.koog:prompt-executor-openai-client:1.1.1 + http-client-okhttp
- LlmClient: OpenAILLMClient(apiKey, baseUrl=llm.binom.pw) → chat(история)
- BuildConfig LLM_API_KEY/LLM_MODEL из local.properties (вне git); llm_debug
smoke (--ez llm_debug true) — проверен на эмуляторе: реальный ответ от
llm.binom.pw (deepseek-v4-flash).
- ЗАГЛУШКА Coroutines_jvmKt: дефект публикации Koog 1.1.1 — utils-android не
включает jvm-класс, который зовёт OkHttpKoogHttpClient (без неё
NoClassDefFoundError на первом вызове). Сигнатура сверена с utils-jvm.
Убрать после фикса JetBrains.
2026-08-20 11:52:50 +03:00
Hermes Agent
3ed63012f4
build: Kotlin 2.2.0 → 2.4.10 (AGP 8.9.2, Gradle 8.14 — в официальном диапазоне)
...
- libs.versions.toml: kotlin = 2.4.10
- jvmTarget '17' (kotlinOptions, String) — в 2.4.10 ошибка → compilerOptions DSL
(JvmTarget.JVM_17) в app-phone и app-glasses
- Compose-плагин (org.jetbrains.kotlin.plugin.compose) версионируется с Kotlin — 2.4.10
- Проверено: lib-core allTests + phone/glasses тесты + оба APK — BUILD SUCCESSFUL
- Открывает дорогу Koog (требует Kotlin 2.3.10+)
2026-08-20 10:51:07 +03:00
Hermes Agent
1304c6d921
feat: голосовой ввод на очках — TripleClick + PCM → телефон → текст на очки
...
Протокол: SttAudio (PCM s16 16k mono кусками), SttPhrase/SttDone/SttCancel
(host→очки), StopStt(cancel) (очки→host).
Очки: TripleClick — безусловный вызов (кино: пауза + затемнение + слушаем);
во время распознавания Click — завершить (весь текст в консоль, затемнение
уходит, видео на паузе), DoubleClick — отмена; VAD-тишина 30с — автоотмена.
Микрофон (AudioRecord 16k) → SttAudio; на эмуляторе — PCM из filesDir/samples
(куски 3200 + пауза 200мс). Оверлей текста в Binocular (полупрозрачный фон,
текст по центру, в оба глаза). RECORD_AUDIO в манифесте. DEBUG-ресивер
(am broadcast DEBUG_GESTURE type=triple_click|click|double_click).
Телефон: SttStreamer — стриминговый VAD (Silero fp32, окна 512) → фразы →
Whisper-small int8 (executor, не блокирует приём) → SttPhrase на очки;
StopStt → SttDone (полный текст) / SttCancel; watchdog 30с тишины.
Фиксы (найдены на эмуляторе): IllegalThreadStateException — двойной старт
watchdog-потока (thread{}.apply{start()}); decode входящих — try/catch с
логом (не роняет сессию).
Проверено на эмуляторах (5554 очки + 5556 телефон, forward 8080):
triple_click → фразы «Раз, два» и «3 4 5» на очках (оверлей) → click →
«ВЕСЬ ТЕКСТ: Раз, два 3 4 5»; 30с-тишина → «отменено». Тесты: lib-core,
phone, glasses — зелёные.
2026-08-20 04:12:28 +03:00
Hermes Agent
324c427c74
feat(app-phone): офлайн-распознавание речи — sherpa-onnx + Whisper-small
...
STT-модуль для отладки (без UI): WhisperStt (offline whisper int8, CPU),
VadSegmenter (Silero VAD, фразы), WavReader (16k mono s16), SttDebug
(распознавание wav-файла по фразам с печатью в лог). Вызов: am start
--ez stt_debug true (первый wav из filesDir/samples). Модели — в
filesDir/models (вне git): small-encoder/decoder.int8.onnx,
small-tokens.txt, silero_vad.onnx (fp32!).
Грабли, найденные на эмуляторе (Android 15):
- Silero VAD int8 (643КБ) молчит в Android-рантайме — нужна fp32 (2.2МБ)
- WavReader: littleShort возвращал беззнаковое 0..65535 — сэмплы с
DC-offset, whisper давал мусор; теперь знаковый -32768..32767
- VAD требует подачу окнами ровно window_size (целиком — переполнение)
- Модели кладутся через adb push /data/local/tmp + run-as cp
(внешний каталог приложения на Android 15 не видит adb-файлы)
Проверено на эмуляторе (CPU): «раз два три четыре пять» → «Раз, два 3 4 5»,
грека → почти идеально, masha/anton → 21 фраза, диалог распознан.
README: таблица жестов обновлена (TripleClick — безусловный вызов).
2026-08-20 03:29:57 +03:00
Hermes Agent
97aaabeb65
fix(app-glasses): не застревать на fallback 10.0.2.2 — перепоиск телефона
...
Если при старте очков телефон недоступен, discoverPhoneUrl возвращал
fallback (эмуляторный 10.0.2.2), он запоминался как lastUrl — очки вечно
реконнектили туда. Теперь на устройстве fallback не используется: не
нашли — повторный поиск через 3с (connectLoop рекурсивно). На эмуляторе
fallback остался. Железо: очки сами нашли телефон после его включения.
2026-08-20 01:41:43 +03:00
Hermes Agent
2844d6a3ac
feat: разделение контента — на телефон только аудио, на очки только видео
...
Телефон качает audio-N.ogg (audioKeys вместо fileKeys, стадия «звук»),
очки получают DownloadFiles только с video.mkv (buildGlassesFileSpecs).
Watch проверяет готовность обоих: телефон — audioReady(), очки — как
было; отказ с подсказкой «Скачать на телефон/очки». Тесты: lib-core 19,
phone 36.
2026-08-20 01:41:43 +03:00
Hermes Agent
9f1c6735c1
feat(app-glasses): AR-метка RayNeoX2 (com.rayneo.mercury.app) + тема + landscape
...
Из pair-view: meta-data com.rayneo.mercury.app=true — очки распознают
приложение как AR (без неё открывалось как обычное). Тема
Theme.ViewMateGlasses (чёрный фон, fullscreen), screenOrientation
landscape, hardwareAccelerated. Плюс фикс краша: prefs читались в
конструкторе Application (до attachBaseContext) — перенесено в onCreate.
Проверено на железе: открывается через лаунчер нормально.
2026-08-20 01:22:27 +03:00
Hermes Agent
896185244b
fix(app-glasses): scale на паузе — принудительная перерисовка кадра
...
На паузе ExoPlayer не шлёт кадры — поверхность меняла размер/позицию,
но кадр оставался старым (часть видео не видно). requestRedraw():
updateTexImage + drawFrame для всех outputs — вызывается при смене
scale (LaunchedEffect) и в surfaceChanged. Подтверждено на железе.
2026-08-20 00:52:21 +03:00
Hermes Agent
9f20093bbf
fix(app-glasses): панель статуса — по центру в оба глаза, процент цветной
...
Binocular-контент растягивался на весь 1280 (fillMaxSize внутри
PositionedBox) — панель оказывалась по центру экрана, половина в каждом
глазу. Теперь явная ширина половины (как у видео-Row) — панель по центру
каждой половины, бинокулярно сливается в одну. ConnectionScreen тоже
обёрнут в Binocular. Квадратик-индикатор убран — процент окрашивается
цветом статуса (зелёный/белый/красный). Скрин: обе половины идентичны.
2026-08-20 00:24:12 +03:00
Hermes Agent
3f858c4a1a
feat(app-glasses): панель статуса — время + заряд (цвет по статусу)
...
Поверх видео (GL-оверлей в EglVideoRenderer: bitmap-текстура, правый
верхний угол, обе поверхности) и композ-панель на экране соединения.
Цвета (из удачной панели pair-view StatusComponent): CHARGING/FULL —
зелёный, DISCHARGING — белый, NOT_CHARGING — красный.
Данные: StatusPanelProvider (sticky ACTION_BATTERY_CHANGED + тик 1с,
HH:mm). Тесты 4 (chargeColorArgb). Железо: «00:02 94%» + зелёный
квадрат (очки на зарядке), скрин подтверждён.
2026-08-20 00:03:23 +03:00
Hermes Agent
2b6fdb7148
fix(app-glasses): старт быстрее — mDNS-таймаут 15с → 3с
...
На RayNeo mDNS мёртв (WiFi режет multicast, 0 пакетов) — 15с уходили
впустую перед сканом /24. Теперь: mDNS 3с → скан ~1с → коннект.
Железо: старт до соединения ~9с (было ~17с).
2026-08-19 23:47:28 +03:00
Hermes Agent
cc3dac7a54
fix(app-glasses): фон очков чёрный полностью
...
ConnectionScreen был без фона — светлый MaterialTheme. Теперь
darkColorScheme + чёрный Box-корень вокруг обоих экранов + страховка
background(Color.Black) в ConnectionScreen. Проверено скрином:
все пиксели #000000 .
2026-08-19 23:42:31 +03:00
Hermes Agent
53a0ffd3dc
docs: TESTING.md OFF9 (жесты), notes 49
2026-08-19 23:38:54 +03:00
Hermes Agent
345e7b74fa
feat(app-glasses): жесты RayNeo SDK (TempleAction) + отключение звуков трекпада
...
Перенос из pair-view (проверено на железе): RayNeoARSDK V0.1.3 (aar в
libs/, MercurySDK.init в GlassesApp), MainActivity → BaseEventActivity,
templeActionViewModel.state → команды (Click=пауза/плей, SlideForward/
Backward=±30с), dispatchTouchEvent→onTouchEvent + toggleSoundEffect(0..3,
false) — системные щелчки трекпада отключены.
Фиксы по ходу (железо):
- applyMediaCommand(msg, onDone) — sendPlaybackPositionNow после seekTo
(иначе телефон получал позицию ДО seek)
- догонка seekTo через 1с на телефоне (первый seekTo в ogg неточен)
- playbackPosition: isPlaying → playWhenReady — ложное playing=false при
буферизации после seekTo паузило звук на телефоне (~5с «пропажи»);
pauseIfPlaying тоже по playWhenReady
Тесты: glasses 59+5, phone 71. Железо: клик пауза/плей ✓, свайпы ±30с ✓,
звук при seek не пропадает ✓ (подтверждено пользователем)
2026-08-19 23:38:45 +03:00
Hermes Agent
654a5f9e26
fix(app-phone): аппаратный back — детали → каталог, инфо об очках → пульт
...
BackHandler в ViewMateApp (DETAILS → CATALOG, GLASSES_INFO → GLASSES);
раньше системная кнопка сворачивала приложение. Проверено на железе.
2026-08-19 22:59:07 +03:00