Вклад в разработку
Спасибо за ваш вклад в Hermes Agent! Это руководство охватывает настройку окружения для разработки, понимание кодовой базы и процесс принятия вашего PR.
Приоритеты вклада
Мы ценим вклад в следующем порядке:
-
Исправление ошибок — сбои, некорректное поведение, потеря данных
-
Кроссплатформенная совместимость — macOS, разные дистрибутивы Linux, WSL2
-
Повышение безопасности — shell-инъекции, prompt-инъекции, path traversal
-
Производительность и надёжность — логика повторных попыток, обработка ошибок, корректная деградация
-
Новые навыки — полезные для широкой аудитории (см. Creating Skills)
-
Новые инструменты — редко требуются; большинство возможностей должны быть навыками
-
Документация — исправления, уточнения, новые примеры
Распространённые направления вклада
-
Создаёте пользовательский/локальный инструмент без изменения ядра Hermes? Начните с Build a Hermes Plugin
-
Создаёте новый встроенный инструмент для самого Hermes? Начните с Adding Tools
-
Создаёте новый навык? Начните с Creating Skills
-
Создаёте нового провайдера инференса? Начните с Adding Providers
Настройка окружения для разработки
Предварительные требования
| Требование | Примечания |
|---|---|
| Git | С поддержкой --recurse-submodules и установленным расширением git-lfs |
| Python 3.11+ | uv установит его, если он отсутствует |
| uv | Быстрый менеджер пакетов Python (установить) |
| Node.js 20+ | Опционально — требуется для инструментов браузера и WhatsApp bridge (соответствует engines в корневом package.json) |
Клонирование и установка
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
# Create venv with Python 3.11
uv venv venv --python 3.11
export VIRTUAL_ENV="$(pwd)/venv"
# Install with all extras (messaging, cron, CLI menus, dev tools)
uv pip install -e ".[all,dev]"
# tinker-atropos is a git submodule — needs `git submodule update --init` first
# if you didn't clone with `--recurse-submodules`
uv pip install -e "./tinker-atropos"
# Optional: browser tools
npm install
Настройка для разработки
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
cp cli-config.yaml.example ~/.hermes/config.yaml
touch ~/.hermes/.env
# Add at minimum an LLM provider key:
echo 'OPENROUTER_API_KEY=***' >> ~/.hermes/.env
Запуск
# Symlink for global access
mkdir -p ~/.local/bin
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
# Verify
hermes doctor
hermes chat -q "Hello"
Запуск тестов
pytest tests/ -v
Стиль кода
-
PEP 8 с практическими исключениями (без строгого ограничения длины строки)
-
Комментарии: Только для пояснения неочевидных намерений, компромиссов или особенностей API
-
Обработка ошибок: Перехватывайте конкретные исключения. Используйте
logger.warning()/logger.error()сexc_info=Trueдля неожиданных ошибок -
Кроссплатформенность: Никогда не предполагайте Unix (см. ниже)
-
Пути, безопасные для профилей: Никогда не указывайте жёстко
~/.hermes— используйтеget_hermes_home()изhermes_constantsдля путей в коде иdisplay_hermes_home()для сообщений пользователю. См. AGENTS.md для полных правил.
Кроссплатформенная совместимость
Hermes официально поддерживает Linux, macOS, WSL2 и нативный Windows (ранняя бета — установка через PowerShell). Нативный Windows использует Git Bash (из Git for Windows) для shell-команд. Некоторые функции требуют примитивов ядра POSIX и ограничены: встроенная PTY-терминальная панель дашборда (вкладка /chat) доступна только в WSL2. Путь нативного Windows новый и быстро развивается — если вы разрабатываете с активным использованием Windows, ожидайте шероховатостей.
При написании кода помните об этих правилах:
-
Не добавляйте незащищённые ссылки на
signal.SIGKILL. Он не определён в Windows. Либо используйтеgateway.status.terminate_pid(pid, force=True)(централизованный примитив, который вызываетtaskkill /T /Fна Windows и SIGKILL на POSIX), либо используйте запасной вариант сgetattr(signal, "SIGKILL", signal.SIGTERM). -
Перехватывайте
OSErrorвместе сProcessLookupErrorпри проверкахos.kill(pid, 0). Windows вызываетOSError(WinError 87, "parameter is incorrect") для уже завершённого PID вместоProcessLookupError. -
Не принуждайте терминал к семантике POSIX.
os.setsid,os.killpg,os.getpgid,os.fork— все вызывают ошибку на Windows; защищайте их условиемif sys.platform != "win32":илиif os.name != "nt":. -
Открывайте файлы с явным указанием
encoding="utf-8". Стандартная кодировка Python на Windows — системная локаль (часто cp1252), которая приводит к кракозябрам или сбоям на нелатинском тексте. -
Используйте
pathlib.Path/os.path.join— никогда не конкатенируйте вручную через/. Это менее важно для строк, возвращаемых ОС, и более важно для строк, которые мы конструируем для передачи подпроцессам.
Ключевые паттерны:
1. termios и fcntl доступны только в Unix
Всегда перехватывайте и ImportError, и NotImplementedError:
try:
from simple_term_menu import TerminalMenu
menu = TerminalMenu(options)
idx = menu.show()
except (ImportError, NotImplementedError):
# Fallback: numbered menu
for i, opt in enumerate(options):
print(f" {i+1}. {opt}")
idx = int(input("Choice: ")) - 1
2. Кодировка файлов
Некоторые окружения могут сохранять .env файлы в кодировках, отличных от UTF-8:
try:
load_dotenv(env_path)
except UnicodeDecodeError:
load_dotenv(env_path, encoding="latin-1")
3. Управление процессами
os.setsid(), os.killpg() и обработка сигналов различаются на разных платформах:
import platform
if platform.system() != "Windows":
kwargs["preexec_fn"] = os.setsid
4. Разделители путей
Используйте pathlib.Path вместо конкатенации строк через /.
Вопросы безопасности
Hermes имеет доступ к терминалу. Безопасность имеет значение.
Существующие механизмы защиты
| Уровень | Реализация |
|---|---|
| Передача пароля sudo | Использует shlex.quote() для предотвращения shell-инъекций |
| Обнаружение опасных команд | Регулярные выражения в tools/approval.py с запросом подтверждения пользователя |
| Защита от prompt-инъекций в Cron | Сканер блокирует паттерны переопределения инструкций |
| Список запрета на запись | Защищённые пути разрешаются через os.path.realpath() для предотвращения обхода через симлинки |
| Защита навыков | Сканер безопасности для навыков, установленных из хаба |
| Песочница выполнения кода | Дочерний процесс запускается без ключей API |
| Усиление контейнера | Docker: все возможности отключены, без повышения привилегий, лимиты PID |
Вклад в код, связанный с безопасностью
-
Всегда используйте
shlex.quote()при интерполяции пользовательского ввода в shell-команды -
Разрешайте симлинки через
os.path.realpath()перед проверками контроля доступа -
Не логируйте секреты
-
Перехватывайте широкие исключения при выполнении инструментов
-
Тестируйте на всех платформах, если ваше изменение затрагивает пути к файлам или процессы
Процесс Pull Request
Именование веток
fix/description # Bug fixes
feat/description # New features
docs/description # Documentation
test/description # Tests
refactor/description # Code restructuring
Перед отправкой
-
Запустите тесты:
pytest tests/ -v -
Протестируйте вручную: Запустите
hermesи проверьте изменённый код -
Проверьте кроссплатформенное влияние: Учтите macOS и разные дистрибутивы Linux
-
Держите PR сфокусированными: Одно логическое изменение на один PR
Описание PR
Включите:
-
Что изменилось и почему
-
Как это тестировать
-
На каких платформах вы тестировали
-
Ссылки на связанные issues
Commit-сообщения
Мы используем Conventional Commits:
<type>(<scope>): <description>
| Тип | Использование |
|---|---|
fix |
Исправление ошибок |
feat |
Новые функции |
docs |
Документация |
test |
Тесты |
refactor |
Реструктуризация кода |
chore |
Сборка, CI, обновление зависимостей |
Области: cli, gateway, tools, skills, agent, install, whatsapp, security
Примеры:
fix(cli): prevent crash in save_config_value when model is a string
feat(gateway): add WhatsApp multi-user session isolation
fix(security): prevent shell injection in sudo password piping
Сообщение об ошибках
-
Используйте GitHub Issues
-
Укажите: ОС, версию Python, версию Hermes (
hermes version), полный стек ошибки -
Приложите шаги для воспроизведения
-
Проверьте существующие issues перед созданием дубликатов
-
Для уязвимостей безопасности, пожалуйста, сообщайте приватно
Сообщество
-
Discord: discord.gg/NousResearch
-
GitHub Discussions: Для предложений по дизайну и обсуждения архитектуры
-
Skills Hub: Загружайте специализированные навыки и делитесь с сообществом
Лицензия
Внося вклад, вы соглашаетесь, что ваши изменения будут лицензированы под MIT License.