Системные уведомления: транспорт Web Push, события агента, настройки (0.88)
О работе агента владелец узнавал только из открытой вкладки: SSE-кадры
task.claimed/task.review живут ровно столько, сколько она открыта, а агент
работает как раз тогда, когда вкладки нет. Web Push — второй транспорт тех же
событий на той же шине; SSE остаётся за мгновенный refetch интерфейса.

Backend: pywebpush и пара ключей VAPID (app/vapid.py печатает готовые строки
для .env; пустые ключи — push тихо выключен, а не падение на старте),
таблица push_subscriptions (endpoint уникален глобально: тот же браузерный
профиль может войти другим аккаунтом — подписка перепривязывается),
app/api/push.py (config/subscribe/unsubscribe/subscriptions), тексты
уведомлений на ru/en/uk собирает сервер — у service worker локалей нет.
Отправка идёт вне HTTP-ответа (BackgroundTasks в REST, поток в MCP) со своей
сессией; мёртвые подписки (404/410, серия ошибок) удаляются лениво.

Frontend: свой src/sw.ts через strategies: 'injectManifest' — в generateSW
обработчик push вставить некуда; precache, SPA-fallback и CacheFirst переехали
из vite.config.ts в воркер, у SW отдельный tsconfig (WebWorker не уживается с
DOM). Подавление при видимой вкладке — по visibilityState клиента, иначе
системное уведомление дублировало бы тост. Разрешение спрашиваем при входе
(жеста нет — браузер вправе проигнорировать), надёжный путь — переключатель
в Настройках.

Тесты: подписка/отписка/перепривязка, отправка с подменённым webpush, связка
событий. Фоновую отправку в тестах глушим: она идёт в чужом потоке по общему
SQLite-соединению и перемешивала транзакции тестов мандата.

ТЗ 0.88: §3.21 «Системные уведомления», правки §3.14, §3.15, §5, §7.
1 parent 309ae81 commit 496ae03f5f00dfb0bfe2a80675d2e40ce503625d
@root root authored 8 hours ago
Showing 34 changed files
View
.env.example
View
backend/alembic/versions/c1d2e3f4a5b6_push_subscriptions.py 0 → 100644
View
backend/app/api/push.py 0 → 100644
View
backend/app/api/tasks.py
View
backend/app/config.py
View
backend/app/main.py
View
backend/app/mcp_server.py
View
backend/app/models.py
View
backend/app/schemas.py
View
backend/app/services/push.py 0 → 100644
View
backend/app/services/push_texts.py 0 → 100644
View
backend/app/vapid.py 0 → 100644
View
backend/pyproject.toml
View
backend/tests/conftest.py
View
backend/tests/test_events.py
View
backend/tests/test_push_api.py 0 → 100644
View
backend/tests/test_push_service.py 0 → 100644
View
backend/uv.lock
View
docs/TZ.md
View
frontend/nginx.conf
View
frontend/package-lock.json
View
frontend/package.json
View
frontend/src/App.vue
View
frontend/src/api.ts
View
frontend/src/locales/en.ts
View
frontend/src/locales/ru.ts
View
frontend/src/locales/uk.ts
View
frontend/src/push.ts 0 → 100644
View
frontend/src/sw.ts 0 → 100644
View
frontend/src/views/SettingsView.vue
View
frontend/tsconfig.app.json 0 → 100644
View
frontend/tsconfig.json
View
frontend/tsconfig.worker.json 0 → 100644
View
frontend/vite.config.ts