Add agent hub UI: registry, connect modal with healthcheck, base URL switching #9

Merged
forgejo-admin merged 1 commit from feature/6_agent_hub_stage_b into main 2026-09-26 09:47:34 +00:00
Collaborator

Что сделано

UI-часть плана хаба агентов (#1, этап B, #6). Изменения только в public/ — серверная часть не тронута (этап A, #5 уже в main).

  1. Реестр агентов — список подключений в localStorage (ключ watcherenish-agents): имя, адрес (нормализуется до origin), Bearer-токен, описание. Прежний токен одного сервера (watcherenish-token) продолжает работать как токен локального агента — миграция не нужна.
  2. Модалка «Подключить агента» — форма (имя, адрес, токен, описание). После подтверждения — GET /api/health агента с таймаутом 5 с:
    • нет соединения/таймаут → «Машина/порт недоступны»;
    • TCP есть, но браузер заблокировал cross-origin запрос → отдельное сообщение «добавьте адрес хаба в ALLOWED_ORIGINS на агенте» (частый случай, отличаем от «машина недоступна» пробным no-cors-запросом);
    • 401 → «Сервис отвечает, но токен неверный»;
    • 200 → агент добавлен в реестр и сразу выбирается активным.
  3. Переключатель агентов в шапке — селект «Локальный агент / подключённые»; все fetch идут к base URL выбранного агента, текущий экран перечитывается при переключении (как и раньше — через route()).
  4. Токен в шапке теперь редактирует токен активного агента (локального или из реестра).
  5. Существующие экраны (сводка, сессии, транскрипт, gate.log) — без изменения логики, только база запросов.

Критерии приёмки (проверено в браузере)

  • Второй агент добавляется через форму; healthcheck отрабатывает все состояния с понятными сообщениями (проверено против реального инстанса с AUTH_TOKEN: недоступен / неверный токен / OK; дополнительно — CORS-блокировка).
  • Переключение агента в шапке меняет base URL всех API-вызовов; данные экрана соответствуют выбранному агенту (дашборд: 53 сессии локально ↔ 0 на стенде с пустым SESSIONS_DIR).
  • Same-origin сценарий работает без деградации (пустой base URL = прежние относительные запросы; все 33 теста зелёные).
  • Реестр переживает перезагрузку страницы.

Как проверить

  1. npm test — 33 теста зелёные (UI-тестов в проекте нет, проверка — в браузере).
  2. npm start, открыть http://127.0.0.1:8787 → шапка: селект «Агент», кнопка «+ Агент».
  3. Поднять второй инстанс с AUTH_TOKEN=secret PORT=8788 ALLOWED_ORIGINS=http://127.0.0.1:8787 и подключить его: + Агент → 127.0.0.1:8788 + токен; попробовать неверный токен (401-сообщение) и выключенный порт («недоступны»).
  4. Переключать агентов в шапке — данные экрана меняются вместе с агентом; F5 — выбранный агент и реестр сохраняются.

Closes #6

## Что сделано UI-часть плана хаба агентов (#1, этап B, #6). Изменения только в `public/` — серверная часть не тронута (этап A, #5 уже в main). 1. **Реестр агентов** — список подключений в `localStorage` (ключ `watcherenish-agents`): имя, адрес (нормализуется до origin), Bearer-токен, описание. Прежний токен одного сервера (`watcherenish-token`) продолжает работать как токен локального агента — миграция не нужна. 2. **Модалка «Подключить агента»** — форма (имя, адрес, токен, описание). После подтверждения — `GET /api/health` агента с таймаутом 5 с: - нет соединения/таймаут → «Машина/порт недоступны»; - TCP есть, но браузер заблокировал cross-origin запрос → отдельное сообщение «добавьте адрес хаба в ALLOWED_ORIGINS на агенте» (частый случай, отличаем от «машина недоступна» пробным `no-cors`-запросом); - `401` → «Сервис отвечает, но токен неверный»; - `200` → агент добавлен в реестр и сразу выбирается активным. 3. **Переключатель агентов в шапке** — селект «Локальный агент / подключённые»; все `fetch` идут к base URL выбранного агента, текущий экран перечитывается при переключении (как и раньше — через `route()`). 4. Токен в шапке теперь редактирует токен **активного** агента (локального или из реестра). 5. Существующие экраны (сводка, сессии, транскрипт, gate.log) — без изменения логики, только база запросов. ## Критерии приёмки (проверено в браузере) - [x] Второй агент добавляется через форму; healthcheck отрабатывает все состояния с понятными сообщениями (проверено против реального инстанса с `AUTH_TOKEN`: недоступен / неверный токен / OK; дополнительно — CORS-блокировка). - [x] Переключение агента в шапке меняет base URL всех API-вызовов; данные экрана соответствуют выбранному агенту (дашборд: 53 сессии локально ↔ 0 на стенде с пустым `SESSIONS_DIR`). - [x] Same-origin сценарий работает без деградации (пустой base URL = прежние относительные запросы; все 33 теста зелёные). - [x] Реестр переживает перезагрузку страницы. ## Как проверить 1. `npm test` — 33 теста зелёные (UI-тестов в проекте нет, проверка — в браузере). 2. `npm start`, открыть `http://127.0.0.1:8787` → шапка: селект «Агент», кнопка «+ Агент». 3. Поднять второй инстанс с `AUTH_TOKEN=secret PORT=8788 ALLOWED_ORIGINS=http://127.0.0.1:8787` и подключить его: `+ Агент` → `127.0.0.1:8788` + токен; попробовать неверный токен (401-сообщение) и выключенный порт («недоступны»). 4. Переключать агентов в шапке — данные экрана меняются вместе с агентом; F5 — выбранный агент и реестр сохраняются. Closes #6
- Agent registry in localStorage (name, base URL, bearer token, note)
- 'Connect agent' modal: form + GET /api/health with distinct states
  (unreachable / CORS blocked / bad token 401 / ok)
- Agent switcher in header: all API calls use the selected agent's
  base URL, current view re-reads on switch
- Same-origin scenario unchanged (local agent = empty base URL)
- Per-agent token editing via the existing header token field
- Registry persists across page reloads
forgejo-admin deleted branch feature/6_agent_hub_stage_b 2026-09-26 09:47:39 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
forgejo-admin/watcherenish!9
No description provided.