OpenSpec: исследование + tavily-proxy-setup, local-extractor (spec-driven для инфраструктуры)

This commit is contained in:
estorozhenko
2026-09-06 12:12:33 +00:00
commit d1a19ba6cd
26 changed files with 1669 additions and 0 deletions
View File
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-06
@@ -0,0 +1,38 @@
# Design: add-vpn-tunnel-proxy
## Approach
Использовать существующий systemd-юнит `telegram-tunnel.service` (SSH -D :1080 → VPS01). Добавить:
- `Restart=always`, `RestartSec=5` в юнит
- `WantedBy=multi-user.target` + `systemctl enable`
- Healthcheck: cron-скрипт или systemd-таймер, проверяющий `curl --socks5-hostname 127.0.0.1:1080 https://api.tavily.com` (HTTP 200 = жив). Молчит, если всё ок; шумит только при падении (по предпочтению пользователя — тихие watchdogs).
## Files
- `/etc/systemd/system/telegram-tunnel.service` — модифицировать (Restart, enable)
- `/opt/hermes/.hermes/scripts/tunnel_healthcheck.sh` — новый скрипт-вотчдог
- `/opt/hermes/README.md` — обновить (порт 1080, юнит, healthcheck)
## Commands
```bash
# Применение
sudo systemctl daemon-reload
sudo systemctl enable --now telegram-tunnel.service
# Проверка
systemctl is-active telegram-tunnel.service
curl -s -o /dev/null -w "%{http_code}" --socks5-hostname 127.0.0.1:1080 https://api.tavily.com
```
## Rollback
```bash
sudo systemctl disable telegram-tunnel.service
# восстановить исходный юнит из бэкапа
```
## Risks
- SSH-ключ должен быть доступен сервису (owner root) — проверить права
- VPS01 недоступен → туннель падает → healthcheck молчит/шумит по порогу
@@ -0,0 +1,24 @@
## Why
Нужен постоянный SOCKS5-туннель до VPS01 для обхода региональных блокировок (Tavily API, Telegram). Сейчас туннель поднимается вручную (SSH -D :1080), что ненадёжно: после ребута теряется, нет мониторинга, нет автозапуска.
## What Changes
- Создать systemd-юнит `telegram-tunnel.service` (уже существует) → **BREAKING**: перевести на автозапуск + watchdog
- Добавить автозапуск при старте (systemctl enable)
- Добавить проверку живости туннеля (systemd watchdog + healthcheck curl через туннель)
- Задокументировать порт 1080 и ключ SSH в README
## Capabilities
### New Capabilities
- `tunnel-proxy`: Постоянный SOCKS5-туннель до VPS01 с автозапуском и мониторингом
### Modified Capabilities
- (нет)
## Impact
- systemd: новый юнит + enable
- SSH: ключ /mnt/yandex-disk/.ssh_box/timewebVPS
- README.md в /opt/hermes (порты)
@@ -0,0 +1,30 @@
# Delta for tunnel-proxy
## ADDED Requirements
### Requirement: Persistent SOCKS5 Tunnel
The system MUST maintain a persistent SOCKS5 proxy tunnel from the host to VPS01, listening on 127.0.0.1:1080.
#### Scenario: Tunnel starts on boot
- GIVEN the host boots
- WHEN systemd starts telegram-tunnel.service
- THEN the tunnel listens on 127.0.0.1:1080
- AND the SSH connection is established with key /mnt/yandex-disk/.ssh_box/timewebVPS
#### Scenario: Tunnel dies
- GIVEN the tunnel process exits unexpectedly
- WHEN systemd detects failure
- THEN the service restarts automatically (Restart=always)
### Requirement: Tunnel Health Monitoring
The system MUST verify tunnel liveness at least every 60 seconds.
#### Scenario: Health check passes
- GIVEN the tunnel is running
- WHEN checking connectivity through 127.0.0.1:1080
- THEN curl through the proxy returns HTTP 200 for a known endpoint
#### Scenario: Health check fails
- GIVEN the tunnel is down
- WHEN the watchdog fires
- THEN a notification is raised (no routine "all ok" messages)
@@ -0,0 +1,14 @@
# Tasks
## 1. Модифицировать юнит telegram-tunnel.service
- [x] 1.1 Добавить Restart=always, RestartSec=5 (бэкап юнита перед правкой)
- [x] 1.2 Включить автозапуск: sudo systemctl enable telegram-tunnel.service
- [x] 1.3 Перезагрузить и проверить: systemctl is-active telegram-tunnel.service
## 2. Healthcheck
- [x] 2.1 Создать /opt/hermes/.hermes/scripts/tunnel_healthcheck.sh (curl через :1080 → tavily; молчит при ок)
- [x] 2.2 Добавить в cron (no_agent) или systemd-таймер на 60s
- [x] 2.3 Проверить: скрипт возвращает тишину при живом туннеле, сообщение при мёртвом
## 3. Документация
- [x] 3.1 Обновить /opt/hermes/README.md: порт 1080, юнит, healthcheck, ключ SSH
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-06
@@ -0,0 +1,45 @@
# Design: tavily-proxy-setup
## Approach
Tavily API блокирует РФ-адреса (403 на уровне AWS ELB). Решение — не менять глобально прокси Hermes (сломало бы прямой доступ к deepseek/polza), а завернуть только Tavily в локальный форвардер:
- `tavily_proxy.py` — http.server на 127.0.0.1:8971, принимает POST на /extract и /search, проксирует через httpx-клиент с SOCKS5-транспортом (`socks5://127.0.0.1:1080`, туннель до VPS01).
- Hermes настраивается на `TAVILY_BASE_URL=http://127.0.0.1:8971` — официальный способ подменить endpoint, httpx-провайдер Tavily шлёт запросы туда.
- Зависимость от туннеля: `After=telegram-tunnel.service` + `Restart=always`.
## Files
- `/opt/hermes/.hermes/scripts/tavily_proxy.py` — форвардер (Python, venv Hermes)
- `/opt/hermes/.hermes/scripts/tavily_extract_proxy.py` — форвардер + локальный экстрактор (trafilatura), юнит указывает на него: `--socks 127.0.0.1:1080 --upstream https://api.tavily.com`
- `/etc/systemd/system/tavily-proxy.service` — юнит (enabled)
- `/opt/hermes/.hermes/.env` — `TAVILY_API_KEY`, `TAVILY_BASE_URL=http://127.0.0.1:8971`
- `/opt/hermes/.hermes/config.yaml` — `web.extract_backend: tavily`
## Commands
```bash
# Применение
sudo systemctl daemon-reload
sudo systemctl enable --now tavily-proxy.service
# Проверка
systemctl is-active tavily-proxy.service
curl -s -o /dev/null -w "%{http_code}" -X POST http://127.0.0.1:8971/extract \
-H "Content-Type: application/json" \
-d '{"urls":["https://example.com"],"api_key":"'"$TAVILY_API_KEY"'"}'
# → 200, web_extract отдаёт контент
```
## Rollback
```bash
sudo systemctl disable --now tavily-proxy.service
# удалить TAVILY_BASE_URL из .env; extract_backend вернуть на searxng (extract не работал — деградация к прежнему состоянию)
```
## Risks
- Туннель VPS01 недоступен → Tavily тоже недоступен (extract лежит) — приемлемо: без туннеля Tavily блокирован в любом случае.
- httpx-SOCKS требует пакет socksio в venv — проверено, есть.
- Форвардер — однопоточный http.server (ThreadingHTTPServer), достаточно для одного агента.
@@ -0,0 +1,24 @@
## Why
Web-экстракция в Hermes сломана: SearXNG умеет только search, а для extract не было ни одного рабочего провайдера. Tavily заблокирован в РФ (403 на AWS ELB). Решение — локальный прокси-форвардер, который ходит в Tavily через существующий SOCKS5-туннель до VPS01.
## What Changes
- Настроен extract_backend=tavily в конфиге Hermes
- Добавлен TAVILY_API_KEY + TAVILY_BASE_URL в /opt/hermes/.hermes/.env
- Создан скрипт /opt/hermes/.hermes/scripts/tavily_proxy.py — локальный HTTP→SOCKS5 форвардер для одного хоста (api.tavily.com)
- Создан systemd-юнит tavily-proxy.service (порт 8971, автозапуск, рестарт)
## Capabilities
### New Capabilities
- `web-extract-tavily`: Веб-экстракция страниц в Hermes через Tavily с обходом региональной блокировки
### Modified Capabilities
- (нет)
## Impact
- /opt/hermes/.hermes/.env — 2 переменные
- /etc/systemd/system/tavily-proxy.service — новый юнит (enabled)
- /opt/hermes/.hermes/scripts/tavily_proxy.py — новый скрипт
@@ -0,0 +1,39 @@
# Delta for web-extract-tavily
## ADDED Requirements
### Requirement: Tavily Extract Backend
The system MUST use Tavily as the web_extract backend, reachable via the local proxy at http://127.0.0.1:8971.
#### Scenario: Extract works
- GIVEN the Hermes web tool calls web_extract
- WHEN the URL is a normal web page
- THEN the page content is returned as markdown
- AND the request goes through the local proxy to the Tavily API over SOCKS5
#### Scenario: Proxy is down
- GIVEN the tavily-proxy.service is stopped
- WHEN web_extract is called
- THEN the call fails with a connection error (not a silent wrong result)
### Requirement: Proxy Auto-Start
The system MUST start tavily-proxy.service automatically at boot and restart it on failure.
#### Scenario: Boot
- GIVEN the host boots
- WHEN systemd starts
- THEN tavily-proxy.service is active
- AND it listens on 127.0.0.1:8971
#### Scenario: Proxy crash
- GIVEN the proxy process exits unexpectedly
- WHEN systemd detects failure
- THEN the service restarts automatically
### Requirement: Tunnel Dependency
The proxy MUST depend on the SOCKS5 tunnel (telegram-tunnel.service); it must not start before the tunnel is up, and must restart if the tunnel is unavailable.
#### Scenario: Tunnel down
- GIVEN telegram-tunnel.service is inactive
- WHEN tavily-proxy.service is requested
- THEN the proxy stays stopped (or retries) until the tunnel is back
@@ -0,0 +1,19 @@
# Tasks
## 1. Скрипт-форвардер
- [x] 1.1 Создать /opt/hermes/.hermes/scripts/tavily_proxy.py (HTTP→SOCKS5, /extract, /search)
## 2. Конфигурация Hermes
- [x] 2.1 web.extract_backend=tavily в config.yaml
- [x] 2.2 TAVILY_API_KEY и TAVILY_BASE_URL в .env
## 3. systemd-юнит
- [x] 3.1 Создать /etc/systemd/system/tavily-proxy.service (After=telegram-tunnel, Restart=always)
- [x] 3.2 enable + запуск: systemctl enable --now tavily-proxy.service
- [x] 3.3 Проверка: active, слушает 127.0.0.1:8971, curl /extract → 200
## 4. Проверка end-to-end
- [x] 4.1 web_extract("https://example.com") через Hermes → успех
## 5. Документация
- [x] 5.1 Зафиксировано: порт 8971, юнит tavily-proxy.service, зависимость от telegram-tunnel.service — в design.md (разделы Files/Commands/Risk) и specs/web-extract-tavily/spec.md