Commit Graph

125 Commits

Author SHA1 Message Date
Cosmo
83f07fa29e perf(voice): prompt-caching для Claude + отсев мёртвых сущностей
All checks were successful
Deploy / deploy (push) Successful in 1m28s
- claudeRequest: system разбит на кэшируемый базовый промпт (cache_control
  ephemeral) + волатильный живой контекст отдельным блоком. Схемы инструментов
  попадают в кэшируемый префикс (render order tools->system) и читаются за ~10%.
- buildLiveContext: пропускаем entity в состоянии unavailable/unknown — меньше
  токенов и шума в снимке.
- Цель: ~20k input/запрос на Haiku давал ~$0.02+/запрос; кэш стабильной части
  (инструменты+база) режет стоимость в разы, ответы не меняются.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UYsVrPyJ5phJeVsAGciS1v
2026-07-22 21:02:15 +00:00
Cosmo
d71320a5a9 fix(voice): агент слушает 0.0.0.0 + защита tool_use.input от null
All checks were successful
Deploy / deploy (push) Successful in 1m58s
- agent/predict.py: HTTPServer bind 127.0.0.1 -> 0.0.0.0, иначе route.ts
  (контейнер планшета) не достукивается до tablet-agent по имени в сети coolify
- route.ts: historyToAnthropicMessages приводит не-объект/null из
  tc.function.arguments к {} — Anthropic 400 (tool_use.input must be object)
  на legacy-истории от Groq (arguments: "null")

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UYsVrPyJ5phJeVsAGciS1v
2026-07-22 20:54:45 +00:00
d.klimov
be0a731738 voice: усиление умного дома — контекст, промпт, новые tools
All checks were successful
Deploy / deploy (push) Successful in 1m52s
- промпт: перечислены ВСЕ 15+ tools, разрешено уверенно управлять домом
- route.ts: живой контекст (время + снимок устройств из HA) в системный промпт
  для LLM-пути (defensive, с таймаутом)
- новые tools: control_climate (кондей/термостат), control_tv, set_scene
  (night/movie/morning/away), all_off, ha_service (универсальный HA с whitelist)
- env: CLIMATE_ENTITY, TV_ENTITY (см. RUNBOOK)
2026-07-22 23:49:50 +03:00
d.klimov
218a7a3acb design: календарь (плотные ячейки, яркий today), приглушён центральный ореол, активная вкладка комнат
All checks were successful
Deploy / deploy (push) Successful in 1m52s
- календарь: ячейки — плотные панели (aurora больше не просвечивает облаком),
  today-ячейка — яркий градиентный акцент с тенью
- центральный aurora-ореол приглушён и убран из центра контента
- активная вкладка комнаты — насыщенный градиент + свечение
2026-07-22 23:39:19 +03:00
d.klimov
d9735d6b71 design: карточки устройств — стеклянное off-состояние + интерактивность
All checks were successful
Deploy / deploy (push) Successful in 2m2s
2026-07-22 23:27:20 +03:00
d.klimov
2755980165 design: красивые пустые состояния таймеров/Spotify, акцентный прогноз
Some checks failed
Deploy / deploy (push) Has been cancelled
- таймеры: светящаяся градиентная иконка + голосовая подсказка вместо серого текста
- Spotify: зелёный музыкальный орб + подсказка
- прогноз: ячейка «сейчас» — яркий градиентный акцент с тенью
2026-07-22 23:25:21 +03:00
d.klimov
d7b1747533 design: градиентный погодный hero, заметные стеклянные карточки, живой ambient
All checks were successful
Deploy / deploy (push) Successful in 2m1s
- погода-hero: насыщенный indigo/violet градиент, крупная анимация справа
  (убирает воид), температура 100px, стеклянные чипы деталей
- карточки заметно светлее (surface-3 glass) — явно поднимаются над фоном
- ambient крупнее и насыщеннее (indigo/cyan/violet) — фон живой, не чёрный
2026-07-22 23:17:41 +03:00
d.klimov
f97b41b848 wake: боевая модель «Эй, космо» (реальная речь Golos в негативах)
All checks were successful
Deploy / deploy (push) Successful in 1m35s
- переобучено на 3594 позитива + 2585 негатива (вкл. корпус Golos)
- held-out: recall 0.984, FP 0.022; проверка через WASM-рантайм pos 1.00 / neg 0.00
- инференс планшета не меняется (окно 25), только веса
- подпись фразы в UI: Космо -> Эй, космо
2026-07-22 22:34:39 +03:00
d.klimov
80ac72ae3c design: стекло-bento карточки, дисплейный шрифт, живой ambient
All checks were successful
Deploy / deploy (push) Successful in 1m38s
- карточки: полупрозрачный градиент + backdrop-blur + inset-подсветка +
  глубокие тени + верхняя градиентная кромка (эффект стекла над aurora)
- Plus Jakarta Sans для заголовков/крупных чисел (выразительнее Inter)
- космическая indigo/aurora палитра, третий ореол глубины
- микро-интеракции (hover-подъём, press-scale) + prefers-reduced-motion
2026-07-22 22:15:00 +03:00
d.klimov
e6dab09c38 voice: локальный агент (fast-path), tool control_light, смелая тема, RUNBOOK
All checks were successful
Deploy / deploy (push) Successful in 3m43s
- lib/agent-local.ts + route.ts: команды-действия исполняет локальная intent-служба
  (под AGENT_URL, с fallback на LLM); инфо-запросы остаются у LLM
- lib/tools/lights.ts: голосовое управление светом через HA (control_light)
- app/globals.css + page.tsx: космическая indigo/aurora тема (токены, kiosk-safe)
- agent/: sidecar-служба (Dockerfile, predict.py), веса монтируются томом
- RUNBOOK.md: вывод в продакшен на мини-ПК
2026-07-22 21:48:24 +03:00
Cosmo
d30ed1bac1 feat: follow-up dialog window — VAD stays active 8s after agent response
All checks were successful
Deploy / deploy (push) Successful in 1m37s
2026-05-01 13:47:51 +00:00
Cosmo
8886d1d907 fix: default Groq model → llama-4-scout, normalize tool_calls type in history
All checks were successful
Deploy / deploy (push) Successful in 1m26s
2026-05-01 13:25:45 +00:00
Cosmo
6199db2977 feat: LLM provider switcher (Claude/Groq) in settings tab
All checks were successful
Deploy / deploy (push) Successful in 1m27s
2026-05-01 12:42:24 +00:00
Cosmo
f8c842b474 fix: use undici ProxyAgent for Anthropic API (native fetch ignores agent)
All checks were successful
Deploy / deploy (push) Successful in 1m30s
2026-05-01 12:21:15 +00:00
Cosmo
bf6a0bdee7 feat: switch voice to direct Anthropic API via proxy
All checks were successful
Deploy / deploy (push) Successful in 1m27s
2026-05-01 12:11:42 +00:00
Cosmo
a8a6de1246 revert: voice/chat back to Groq (ai-proxy not headless-compatible)
All checks were successful
Deploy / deploy (push) Successful in 1m46s
2026-05-01 12:08:16 +00:00
Cosmo
ea096a855b fix: cast role to string for system check (TS type guard)
All checks were successful
Deploy / deploy (push) Successful in 1m35s
2026-05-01 11:37:21 +00:00
Cosmo
130a58637a feat: switch voice from Groq to Claude Haiku via ai-proxy
Some checks failed
Deploy / deploy (push) Failing after 1m0s
2026-05-01 11:34:29 +00:00
Cosmo
d5dc9e6ec9 fix: suppress VAD debug logs via console.debug override
Some checks failed
Deploy / deploy (push) Failing after 44s
2026-05-01 11:27:44 +00:00
Cosmo
a94a40ffc6 fix: suppress VAD debug logs, spotify no-device graceful, filter tool names from response
Some checks failed
Deploy / deploy (push) Failing after 45s
2026-05-01 11:25:15 +00:00
Cosmo
70284c69cf fix: fallback without tools on tool_use_failed error
All checks were successful
Deploy / deploy (push) Successful in 1m28s
2026-05-01 11:19:26 +00:00
Cosmo
feafde37dc feat: Spotify widget on home tab
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-05-01 11:18:51 +00:00
Cosmo
2143ccadab fix: allow spotify OAuth routes without auth cookie
All checks were successful
Deploy / deploy (push) Successful in 1m35s
2026-05-01 11:13:04 +00:00
Cosmo
c43bad1fc3 fix: use docker rm -f to avoid stop/rm conflict in CI
All checks were successful
Deploy / deploy (push) Successful in 4s
2026-05-01 11:10:56 +00:00
Cosmo
9bea298687 feat: Spotify integration (OAuth + voice tools)
Some checks failed
Deploy / deploy (push) Failing after 1m40s
2026-05-01 11:02:11 +00:00
Cosmo
ae7edbe6ed fix: smart-home tool syntax error in else branch
All checks were successful
Deploy / deploy (push) Successful in 1m52s
2026-05-01 07:00:01 +00:00
Cosmo
89d8140014 feat: smart-home voice tools (get_state + control_air_purifier)
Some checks failed
Deploy / deploy (push) Failing after 1m18s
2026-05-01 06:57:43 +00:00
Cosmo
7b5f76576f refactor: tool plugin registry - each tool in separate file
All checks were successful
Deploy / deploy (push) Successful in 1m25s
2026-04-30 20:58:11 +00:00
Cosmo
4ba1aa43d5 feat: switch voice chat from Anthropic to Groq (llama-3.3-70b) + proxy support
All checks were successful
Deploy / deploy (push) Successful in 1m26s
2026-04-30 20:48:02 +00:00
Cosmo
04b7d1f104 feat: switch from Anthropic to Groq API (llama-3.3-70b-versatile)
All checks were successful
Deploy / deploy (push) Successful in 2m47s
- route.ts: replace @anthropic-ai/sdk with groq-sdk, rewrite chat loop
- voice-tool-schemas.ts: convert from Anthropic format to OpenAI/Groq function tools
- voice-history.ts: extend HistoryMessage type to include tool role, simplify cache stubs

No prompt caching (Groq does not support it), tool calling preserved.
2026-04-30 20:43:30 +00:00
Cosmo
96fa78bd5c fix(calendar): GOOGLE_SA_JSON_B64 поддержка (env-file friendly)
All checks were successful
Deploy / deploy (push) Successful in 2m7s
docker --env-file не поддерживает многострочные значения и не парсит
кавычки. Сырой JSON service-account ломается на newline'ах в private_key
поле → docker пытается парсить '-----END PRIVATE KEY-----' как имя
переменной и валится с 'contains whitespaces'.

Решение: base64 GOOGLE_SA_JSON_B64 (одна строка ASCII, никаких кавычек).
Старая GOOGLE_SA_JSON оставлена как fallback. Третий fallback на файл —
для локальной разработки.
2026-04-27 12:59:17 +00:00
Cosmo
be377e377f chore: ignore google-sa.json в git и docker context
Some checks failed
Deploy / deploy (push) Failing after 1m35s
2026-04-27 12:52:47 +00:00
Cosmo
d17e1232f1 security: убираем google-sa.json из репо и Docker image
Some checks failed
Deploy / deploy (push) Has been cancelled
Service Account ключ больше не распространяется через git/image —
читается из env GOOGLE_SA_JSON, которая выставлена в /opt/digital-home/
tablet.env на сервере.

- google-sa.json удалён из git tracking (git rm --cached)
- Добавлен в .gitignore + .dockerignore
- На сервере после git pull файл будет удалён с диска;
  /api/calendar читает credentials из env (env-first fallback уже был
  в коде). Это критично если bundle/image куда-то утечёт — ключ Google
  больше не лежит внутри.
2026-04-27 12:52:36 +00:00
Cosmo
05b300d472 chore(voice): security, cleanup, resilience
All checks were successful
Deploy / deploy (push) Successful in 1m47s
Безопасность:
- Rate-limit на /api/voice/chat (20/мин per cookie/IP, env VOICE_RATE_LIMIT).
  Защищает от случайных циклов и утечки PIN.
- Усечение user prompt'а до 4000 символов в /api/voice/chat.
- Tool-loop защита от циклов: если LLM дважды просит тот же tool с теми же
  args — прерываем (раньше мог уйти в бесконечный цикл при tool error'ах).

Чистка кода:
- lib/debug.ts — vlog/vwarn/verror гейтят браузерные логи за
  NEXT_PUBLIC_VOICE_DEBUG=1 (или localStorage 'voice-debug=1').
  Серверные console.log оставлены — полезны в Docker logs.
- lib/audio-wav.ts — вынесена дублированная floatToWav из VoiceController.
- Удалены orphan компоненты FocusCard.tsx и CountdownCard.tsx
  (не подключены, отвергнуты по UX-фидбеку).

Resilience:
- WakeWordDetector: drop-on-busy в onChunk — на медленных устройствах
  (Android, бюджетный CPU) backlog inference больше не копится.
- voice-history fallback на /tmp/voice-history если /data не примонтирован
  (локальная разработка / нестандартная конфигурация).
2026-04-27 12:44:18 +00:00
Cosmo
3211d62198 fix(voice): COOP/COEP=credentialless → SharedArrayBuffer на iOS
All checks were successful
Deploy / deploy (push) Successful in 1m52s
VAD на iPad валился с «no available backend found / RangeError».
onnxruntime-web 1.24 ships только threaded WASM сборки, которые
требуют SharedArrayBuffer. iOS Safari его не даёт без cross-origin
isolation — отсюда и ошибка.

Добавляем заголовки:
  Cross-Origin-Opener-Policy: same-origin
  Cross-Origin-Embedder-Policy: credentialless

credentialless (а не require-corp) выбрали чтобы не ломать внешние
ресурсы без CORP-заголовка (Google Fonts, wttr.in). Поддержка:
Chrome 96+, Firefox 110+, Safari 16.4+.
2026-04-27 11:30:08 +00:00
Cosmo
6083597065 fix(voice): TTS играет через AudioContext (фикс для iPad Safari)
All checks were successful
Deploy / deploy (push) Successful in 1m45s
iOS Safari блокирует <audio>.play() даже после silent-WAV unlock —
каждый new Audio() считается новым элементом без gesture.

Решение: при тапе кнопки в VoiceController создаём общий
AudioContext (под user-gesture) и пробуждаем его. VoiceOverlay
теперь играет TTS через этот ctx (decodeAudioData + BufferSource).
HTMLAudioElement остаётся fallback'ом если ctx недоступен.

decodeAudioData в Safari исторически callback, в Chrome — Promise:
используем оба варианта.
2026-04-27 11:17:41 +00:00
Cosmo
6c3992bb4e fix(voice): audio unlock на тапе → TTS играет на Android
All checks were successful
Deploy / deploy (push) Successful in 2m1s
Android Chrome требует user-gesture для <audio>.play(). Wake-word
триггерит TTS «сам», без тапа, поэтому play() тихо отвергался.

При тапе на кнопку микрофона теперь проигрываем 1мс silent WAV →
браузер помечает страницу как разрешённую для autoplay в текущей
сессии. Дальше TTS-ответы Cosmo/Lusya играют без проблем.

В VoiceOverlay логируем причину если play() всё ещё отвергнут.
2026-04-27 11:12:27 +00:00
Cosmo
f74b10ba38 fix(voice): откатить VAD preload — мешал wake-word ловить «Космо»
All checks were successful
Deploy / deploy (push) Successful in 1m51s
Параллельный getUserMedia от MicVAD конфликтует со stream'ом wake-word —
видимо Chrome применяет AGC/NS по-разному и wake получает «глухое» аудио.
Score упал с 0.988 до 0.093 — wake перестал срабатывать.

Возвращаемся: VAD создаётся ПОСЛЕ первого wake (~1-2с пауза),
но cancel/onSpeechEnd теперь только pause (не destroy), так что
повторные wake мгновенные.
2026-04-27 11:03:09 +00:00
Cosmo
7e3c5072bb fix(voice): preload VAD один раз — мгновенная реакция после «Космо»
All checks were successful
Deploy / deploy (push) Successful in 1m36s
В логах было видно: между wake-trigger и реальным VAD recording
проходило 1-2с (Loading VAD... → finished loading → started micVAD).
Каждый cancel дополнительно destroy'ил VAD, и следующий wake снова
ждал инициализацию.

Теперь:
- VAD создаётся один раз в paused-режиме сразу после wake.start()
  (в фоне, не блокирует UI).
- На каждый wake → vad.start() мгновенно.
- onSpeechEnd → vad.pause() (был implicit pause; явно ставим).
- voice-cancel → vad.pause(), а не destroy. Wake продолжает слушать.
- destroy только при полном выключении ассистента.
2026-04-27 10:55:18 +00:00
Cosmo
fddca5de66 fix(wake-word): cosmo.onnx ждёт окно из 25 embedding'ов, не 16
All checks were successful
Deploy / deploy (push) Successful in 1m56s
Из ORT-ошибки:
  onnx::Flatten_0 index 1 Got: 16 Expected: 25.

Стоковые openWakeWord модели тренируются на окне 16, наша cosmo.onnx —
на 25. Меняем EMB_WINDOW. Окно для embedding-буфера тоже подвинули,
чтобы хватало для classifier'а.
2026-04-27 10:42:59 +00:00
Cosmo
9583c84e27 feat(voice): кнопка X в overlay закрывает прослушивание
All checks were successful
Deploy / deploy (push) Successful in 2m13s
В overlay появляется крестик в правом верхнем углу. Тап = эмитит
voice-cancel → VoiceController прерывает активный VAD-захват и сам
overlay закрывается. Wake-word, если был активен, продолжает слушать
в фоне.
2026-04-27 10:25:21 +00:00
Cosmo
0ea9fad144 debug(voice): mount + tap логи в консоль
All checks were successful
Deploy / deploy (push) Successful in 2m14s
2026-04-27 10:16:17 +00:00
Cosmo
d7accb5602 ci: install docker-cli-buildx so BuildKit cache mounts work
All checks were successful
Deploy / deploy (push) Successful in 2m57s
2026-04-27 10:01:04 +00:00
Cosmo
463043b43b build: BuildKit cache mounts → CI 3-5× быстрее
Some checks failed
Deploy / deploy (push) Failing after 2s
Текущая сборка ~7 минут — npm ci качает все 183 пакета с нуля + next
build без incremental cache на каждом push.

- Dockerfile: BuildKit cache mount на /root/.npm (npm install) и
  .next/cache (Next.js incremental TS/swc/webpack cache).
- workflow: DOCKER_BUILDKIT=1 чтобы cache mounts работали.
- .dockerignore: убираем node_modules/.next/.git/docs из контекста —
  меньше копирования + чище инвалидация слоёв.
- Поднимаем NODE_OPTIONS heap до 4G в build-стадии (TS падал с OOM).

Первый билд после этого коммита заполнит cache — второй и дальше
будут значительно быстрее (deps install ~5-10с вместо 60-90с,
next build тоже ускорится за счёт incremental).
2026-04-27 09:59:21 +00:00
Cosmo
71124ce565 debug(voice): verbose logging для wake-word pipeline
Some checks failed
Deploy / deploy (push) Has been cancelled
2026-04-27 09:57:56 +00:00
Cosmo
522d36d1a2 feat(voice): wake-word «Космо» в браузере (Шаг 3)
All checks were successful
Deploy / deploy (push) Successful in 6m33s
openWakeWord pipeline на onnxruntime-web прямо на планшете. Цепочка:
mic (16kHz, AudioWorklet) → melspectrogram.onnx → embedding_model.onnx
(sliding 76-frame window, stride 8) → cosmo.onnx → score 0..1.

Триггер при score≥0.5 → запускается тот же VAD-flow что и push-to-talk.

- public/wake/ — cosmo.onnx (custom-trained на голос Даниила) +
  melspectrogram.onnx + embedding_model.onnx (~2.9MB вместе).
- lib/wake-word.ts — WakeWordDetector class. ort грузится через
  <script src=/vad/ort.wasm.min.js> на клиенте — обход проблемы next-swc
  с парсингом import.meta.url в onnxruntime-web .mjs билдах.
- VoiceController: тап = активация (нужен для AudioContext user-gesture),
  далее непрерывное слушание wake-word; на детект → MicVAD флоу.
  Долгий тап = выкл. Ручной тап остаётся как fallback.

После деплоя Python-агент на .103 не нужен — можно архивировать
home-voice-assistant. На .103 остаётся только ElevenLabs прокси :8888.
2026-04-27 09:43:53 +00:00
Cosmo
96bd846a08 fix(voice): ship non-asyncify ort-wasm + force single-thread
All checks were successful
Deploy / deploy (push) Successful in 3m46s
В public/vad/ были только asyncify-варианты, а onnxruntime-web по дефолту
просит ort-wasm-simd-threaded.{mjs,wasm} → 404 → MicVAD init falls.

- Положили ort-wasm-simd-threaded.{mjs,wasm} рядом.
- ortConfig forces numThreads=1, чтобы не требовать SharedArrayBuffer
  (нет COOP/COEP headers и не хотим их вешать на весь сайт).
- Раздельный getUserMedia probe перед VAD init, чтобы отличить отказ
  по микрофону от ошибки VAD/wasm в UI-сообщении.
2026-04-27 09:01:52 +00:00
Cosmo
93bf34f216 feat(voice): push-to-talk button — браузерный mic+VAD pipeline
All checks were successful
Deploy / deploy (push) Successful in 6m53s
Шаг 2 миграции: убираем зависимость от Python-агента для базового
голосового сценария. Тап на круглую кнопку-микрофон в правом нижнем
углу → MicVAD (Silero v5) ловит речь → автостоп по тишине → /api/voice/stt
→ /api/voice/chat → ответ через SSE и TTS как раньше.

- components/VoiceController.tsx — push-to-talk UI + MicVAD orchestration
- VoiceOverlay теперь слушает window CustomEvent('voice-local'), чтобы
  орб моргал ещё до round-trip на сервер (wake/listening мгновенно).
- public/vad/ — silero v5/legacy onnx + ort wasm + audio worklet,
  раздаются через baseAssetPath: '/vad/' (не зависит от внешнего CDN,
  важно если планшет без интернета или с RU-блоком).

Что осталось от home-voice-assistant: только wake-word. После Шага 3
(onnxruntime-web + перенос openwakeword .onnx) Python-агент уйдёт целиком.
2026-04-27 08:48:22 +00:00
Cosmo
eeac2eefb3 feat(voice): server-side LLM/STT — porting Python satellite into tablet
All checks were successful
Deploy / deploy (push) Successful in 5m44s
Шаг 1 миграции голосового стека из home-voice-assistant в сам tablet:

- /api/voice/chat — Claude Haiku 4.5 с tool-loop (max 4 раунда), prompt
  caching на system + старой истории, история в /data/voice-history/.
  Эмитит command/response/error в voice-bus → орб моргает как раньше.
- /api/voice/stt — Groq whisper-large-v3-turbo, multipart или raw audio.
- lib/voice-text.ts — порт clean_for_speech (без pymorphy3, время в
  именительном падеже) и strip_fillers + RESET_PATTERNS.
- lib/voice-executors.ts — tool executors через loopback fetch на
  существующие /api/voice/tools/* и /api/voice/timer.
- Поддержка ANTHROPIC_PROXY/GROQ_PROXY (fallback на HTTPS_PROXY).

После деплоя нужны GROQ_API_KEY и ANTHROPIC_API_KEY в tablet.env.
Шаги 2 (push-to-talk в браузере) и 3 (wake-word) — отдельно.
2026-04-27 08:24:19 +00:00
Cosmo
a97dd11f25 revert(home): restore weather hero with anim + details, drop Countdown from home
All checks were successful
Deploy / deploy (push) Successful in 3m24s
Focus/Countdown не лежат по high-density. На Home вернул старый
weather-hero: WeatherAnimation (фон + иконка), feelsLike/humidity/wind,
76px display-цифра (чуть крупнее прежних 64). FocusCard и CountdownCard
файлы оставляем для будущего, но на главной не подключаем. Убрал
сопутствующие state/fetch (tramNext, countdowns, nextEvent).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:35:01 +00:00