Расширение CLI
Hermes обеспечивает расширение защищенных точек в HermesCLI, чтобы обеспечить CLI дополнительные виджеты, привязки клавиш и макет настройки без переопределения метода run() на протяжении более 1000 строк. Это сохранит вашу независимость от внутренних изменений.
Расширение Точки
Доступно пять точек расширения:
| Хук | Назначение | Переопределите, когда... |
|---|---|---|
_get_extra_tui_widgets() |
Внедрение виджетов в макет | Вам нужен постоянный элемент пользовательского интерфейса (панель, строка состояния, мини-плеер) |
_register_extra_tui_keybindings(kb, *, input_area) |
Добавление сочетаний клавиш | Вам нужны горячие клавиши (переключение панелей, элементы управления, модальные клавиши) |
_build_tui_layout_children(**виджеты) |
Полный контроль над порядком виджетов | Вам нужно изменить порядок или обернуть некоторые виджеты (редко) |
process_command() |
Добавление руководства слэш-команд | Вам нужна обработка /mycommand (существующий хук) |
_build_tui_style_dict() |
Пользовательские стили Prompt_toolkit | Вам нужны пользовательские цвета или стили (существующий хук) |
Первые три — новые защищённые хуки. Последние два уже существовали.
Быстрый запуск: обёртка CLI
#!/usr/bin/env python3
"""my_cli.py — Пример обёртки CLI, расширяющей Hermes."""
from cli import HermesCLI
from prompt_toolkit.layout import FormattedTextControl, Window
from prompt_toolkit.filters import Condition
class MyCLI(HermesCLI):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._panel_visible = False
def _get_extra_tui_widgets(self):
"""Добавляет переключаемую информационную панель над строкой состояния."""
cli_ref = self
return [
Window(
FormattedTextControl(lambda: "📊 Содержимое моей пользовательской панели"),
height=1,
filter=Condition(lambda: cli_ref._panel_visible),
),
]
def _register_extra_tui_keybindings(self, kb, *, input_area):
"""F2 переключает пользовательскую панель."""
cli_ref = self
@kb.add("f2")
def _toggle_panel(event):
cli_ref._panel_visible = not cli_ref._panel_visible
def process_command(self, cmd: str) -> bool:
"""Добавляет slash-команду /panel."""
if cmd.strip().lower() == "/panel":
self._panel_visible = not self._panel_visible
state = "видна" if self._panel_visible else "скрыта"
print(f"Панель теперь {state}")
return True
return super().process_command(cmd)
if __name__ == "__main__":
cli = MyCLI()
cli.run()
Запустите:
cd ~/.hermes/hermes-agent
source.venv/bin/activate
python my_cli.py
Справочник по хукам
_get_extra_tui_widgets()
Возвращает список виджетов Prompt_toolkit для вставок в макет TUI. Виджеты зданий между разделителем и строкой состояния — над областью ввода, но под основным выводом.
def _get_extra_tui_widgets(self) -> list:
return [] # по умолчанию: нет дополнительных виджетов
Каждый виджет должен быть контейнером Prompt_toolkit (например, Window, ConditionalContainer, HSplit). Используйте ConditionalContainer или filter=Condition(...), чтобы сделать виджеты переключаемыми.
from prompt_toolkit.layout import ConditionalContainer, Window, FormattedTextControl
from prompt_toolkit.filters import Condition
def _get_extra_tui_widgets(self):
return [
ConditionalContainer(
Window(FormattedTextControl("Статус: подключено"), height=1),
filter=Condition(lambda: self._show_status),
),
]
_register_extra_tui_keybindings(kb, *, input_area)
Выдается после того, как Гермес регистрирует свои собственные привязки клавиш и строит макет. Добавьте свои привязки клавиш в kb.
def _register_extra_tui_keybindings(self, kb, *, input_area):
pass # по умолчанию: нет дополнительных привязок клавиш
Параметры:
- kb — Экземпляр KeyBindings для приложения Prompt_toolkit
- input_area — Основной виджет TextArea, если вам нужно прочитать или изменить дополнительное введение.
def _register_extra_tui_keybindings(self, kb, *, input_area):
cli_ref = self
@kb.add("f3")
def _clear_input(event):
input_area.text = ""
@kb.add("f4")
def _insert_template(event):
input_area.text = "/search "
Избегайте ошибок с помощью привязок клавиш: Enter (отправка), Escape Enter (новая строка), Ctrl-C (прерывание), Ctrl-D (выход), Tab (принятие автодополнения). Функциональные клавиши F2+ и Ctrl обычно безопасны.
_build_tui_layout_children(**виджеты)
Переопределяйте это только тогда, когда вам понадобится полный контроль над порядком виджетов. Большинству расширений следует использовать _get_extra_tui_widgets().
def _build_tui_layout_children(self, *, sudo_widget, secret_widget,
approval_widget, clarify_widget, model_picker_widget=None,
spinner_widget=None, spacer, status_bar, input_rule_top,
image_bar, input_area, input_rule_bot, voice_status_bar,
completions_menu) -> list:
Реализация по умолчанию возвращает (любимые виджеты None отфильтровываются):
[
Window(height=0), # якорь
sudo_widget, # запрос пароля sudo (условный)
secret_widget, # запрос секретного ввода (условный)
approval_widget, # подтверждение опасной команды (условный)
clarify_widget, # UI уточняющего вопроса (условный)
model_picker_widget, # наложение выбора модели (условный)
spinner_widget, # индикатор размышления (условный)
spacer, # заполняет оставшееся вертикальное пространство
*self._get_extra_tui_widgets(), # ВАШИ ВИДЖЕТЫ РАСПОЛАГАЮТСЯ ЗДЕСЬ
status_bar, # строка состояния модели/токенов/контекста
input_rule_top, # ─── граница над вводом
image_bar, # индикатор прикреплённых изображений
input_area, # пользовательский текстовый ввод
input_rule_bot, # ─── граница под вводом
voice_status_bar, # статус голосового режима (условный)
completions_menu, # выпадающее меню автодополнения
]
Схема макета
Макет по умолчанию сверху вниз:
- Область результата — прокручиваемая история диалога
- Разделитель
- Дополнительные виджеты — из
_get_extra_tui_widgets() - Строка состояния — модель, % контекста, прошедшее время
- Панель изображений — количество прикреплённых изображений.
- Область ввода — пользовательский запрос.
- Статус голоса — индикатор записи.
- Меню автодополнения — предложения автодополнения
Советы
- Обновляйте использование после изменения состояния: вызовите
self._invalidate(), чтобы инициировать перерисовку Prompt_toolkit. - Доступ к состоянию агента:
self.agent,self.model,self.conversation_history— все доступны. - Пользовательские стили: Переопределите
_build_tui_style_dict()и записи записей для ваших файлов стилей. - Slash-команды: Переопределите
process_command(), обработайте свои команды и вызовитеsuper().process_command(cmd)для всего остального. - Не переопределяйте
run()без всякой необходимости — точки расширения существуют именно для того, чтобы избежать такой связанности.