From 44808bdc4e08ebaf2df58c68ffa199a9a25e0961 Mon Sep 17 00:00:00 2001 From: Hermes Team Date: Tue, 25 Aug 2026 10:27:16 +0700 Subject: [PATCH] =?UTF-8?q?feat(web):=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF?= =?UTF-8?q?=D1=82=20=D0=BE=D1=82=D0=BA=D1=80=D1=8B=D1=82=D0=B8=D1=8F=20?= =?UTF-8?q?=D1=85=D0=B0=D0=B1=D0=B0=20=D0=B2=20=D0=B4=D0=BE=D0=BC=D0=B0?= =?UTF-8?q?=D1=88=D0=BD=D1=8E=D1=8E=20=D1=81=D0=B5=D1=82=D1=8C,=20=D1=81?= =?UTF-8?q?=20=D0=BF=D0=BE=D0=B4=D1=82=D0=B2=D0=B5=D1=80=D0=B6=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=D0=BC=20=D1=86=D0=B5=D0=BB=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Владелец хочет попадать в хаб на сервере по сети, а не через SSH-туннель. Для этого нужны привязка к 0.0.0.0 и токен: без токена при небlocalhost привязке сервер отказывается стартовать. Скрипт ДОПОЛНЯЕТ hub_settings.json, а не переписывает: рядом лежат тема, интервал обновления квот и параметры маршрутизации. Запись атомарная, повторный запуск сохраняет прежний токен. Изменение требует явного --yes, а каталог печатается всегда. Причина не теоретическая: при отладке скрипт молча взял HERMES_HOME из окружения и записал настройки не в тестовую копию, а в живой хаб рабочей машины, привязав его к сети. Откачено, наружу ничего не вышло — адрес читается при старте, процесс не перезапускался, netstat подтвердил только 127.0.0.1. Предпросмотр по умолчанию закрывает этот класс ошибки. Попутно install-linux.sh разворачивает scripts/: они входили в поставку, но на установленной машине не оказывались, поэтому вспомогательных инструментов там просто не было. Проверено на копии настроек: предпросмотр не меняет файл, применение сохраняет прежние ключи, повторный запуск не меняет токен, посторонний каталог не затрагивается. Co-Authored-By: Claude Opus 5 --- installer/install-linux.sh | 9 +++++ scripts/enable_lan_access.py | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 scripts/enable_lan_access.py diff --git a/installer/install-linux.sh b/installer/install-linux.sh index d972de2..7fedf90 100644 --- a/installer/install-linux.sh +++ b/installer/install-linux.sh @@ -96,6 +96,15 @@ if [ -d "$REPO_ROOT/assets" ]; then cp -r "$REPO_ROOT/assets/"* "$HERMES_HOME/plugins/antigravity-provider/assets/" 2>/dev/null || true fi +# Deploy helper scripts. Они лежат в поставке, но раньше не разворачивались, +# поэтому вспомогательных инструментов (например открытия хаба в домашнюю сеть) +# на установленной машине просто не оказывалось. +if [ -d "$REPO_ROOT/scripts" ]; then + mkdir -p "$HERMES_HOME/scripts" + cp -r "$REPO_ROOT/scripts/"*.py "$HERMES_HOME/scripts/" 2>/dev/null || true + cp -r "$REPO_ROOT/scripts/"*.sh "$HERMES_HOME/scripts/" 2>/dev/null || true +fi + # 4. Write Deployment Manifest echo "[4/6] Writing deployment manifest..." MANIFEST_FILE="$HERMES_HOME/plugins/antigravity-provider/deployment_manifest.json" diff --git a/scripts/enable_lan_access.py b/scripts/enable_lan_access.py new file mode 100644 index 0000000..de46b07 --- /dev/null +++ b/scripts/enable_lan_access.py @@ -0,0 +1,67 @@ +"""Открыть веб-хаб в домашнюю сеть: привязка к 0.0.0.0 плюс обязательный токен. + + python3 scripts/enable_lan_access.py # показать, что будет сделано + python3 scripts/enable_lan_access.py --yes # применить + +Почему подтверждение обязательно. Каталог берётся из HERMES_HOME, а эта +переменная часто задана в окружении незаметно для запускающего. При отладке +скрипт из-за этого записал настройки не туда, куда предполагалось, и привязал +к сети не тот хаб. Поэтому цель печатается всегда, а изменение требует --yes. + +Настройки ДОПОЛНЯЮТСЯ, а не переписываются: рядом лежат тема, интервал +обновления квот и параметры маршрутизации. Запись атомарная. +""" +import json +import os +import secrets +import sys +from pathlib import Path + + +def main() -> int: + apply = "--yes" in sys.argv + env_home = os.environ.get("HERMES_HOME") + home = Path(env_home) if env_home else (Path.home() / ".hermes") + target = home / "hub_settings.json" + + print(f"Каталог Hermes : {home}") + print(f" источник : {'переменная HERMES_HOME' if env_home else 'по умолчанию ~/.hermes'}") + print(f"Файл настроек : {target}") + print(f" существует : {'да' if target.exists() else 'нет, будет создан'}") + + data = {} + if target.exists(): + try: + data = json.loads(target.read_text(encoding="utf-8")) + except ValueError: + print(f"\nОТКАЗ: {target} повреждён. Разберитесь вручную — перезаписывать не буду.") + return 1 + + existing = data.get("web_api_token") + keep = sorted(k for k in data if not k.startswith("web_api")) + print(f"Будут сохранены: {', '.join(keep) if keep else '(файл пуст)'}") + print(f"Токен : {'уже задан, оставляю прежний' if existing else 'будет создан новый'}") + + if not apply: + print("\nПоказан предпросмотр. Чтобы применить, повторите с --yes") + return 0 + + token = existing or secrets.token_urlsafe(32) + data["web_api_host"] = "0.0.0.0" + data["web_api_token"] = token + data.setdefault("web_api_port", 5800) + + tmp = target.with_suffix(".json.tmp") + tmp.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8") + os.replace(tmp, target) + + print(f"\nГотово: {target}") + print("\nТОКЕН — вставить в «Настройки» в интерфейсе:") + print(f" {token}") + print("\nДальше: перезапустить хаб, затем открыть http://<адрес-сервера>:5800") + print("Токен хранится в этом файле; в снапшот и в /api/settings он не попадает.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())