|
Системные уведомления: транспорт 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. |
|---|
|
|
| .env.example |
|---|
| backend/alembic/versions/c1d2e3f4a5b6_push_subscriptions.py 0 → 100644 |
|---|
| backend/app/api/push.py 0 → 100644 |
|---|
| backend/app/api/tasks.py |
|---|
| backend/app/config.py |
|---|
| backend/app/main.py |
|---|
| backend/app/mcp_server.py |
|---|
| backend/app/models.py |
|---|
| backend/app/schemas.py |
|---|
| backend/app/services/push.py 0 → 100644 |
|---|
| backend/app/services/push_texts.py 0 → 100644 |
|---|
| backend/app/vapid.py 0 → 100644 |
|---|
| backend/pyproject.toml |
|---|
| backend/tests/conftest.py |
|---|
| backend/tests/test_events.py |
|---|
| backend/tests/test_push_api.py 0 → 100644 |
|---|
| backend/tests/test_push_service.py 0 → 100644 |
|---|
| backend/uv.lock |
|---|
| docs/TZ.md |
|---|
| frontend/nginx.conf |
|---|
| frontend/package-lock.json |
|---|
| frontend/package.json |
|---|
| frontend/src/App.vue |
|---|
| frontend/src/api.ts |
|---|
| frontend/src/locales/en.ts |
|---|
| frontend/src/locales/ru.ts |
|---|
| frontend/src/locales/uk.ts |
|---|
| frontend/src/push.ts 0 → 100644 |
|---|
| frontend/src/sw.ts 0 → 100644 |
|---|
| frontend/src/views/SettingsView.vue |
|---|
| frontend/tsconfig.app.json 0 → 100644 |
|---|
| frontend/tsconfig.json |
|---|
| frontend/tsconfig.worker.json 0 → 100644 |
|---|
| frontend/vite.config.ts |
|---|