Расширение 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,       # выпадающее меню автодополнения
]

Схема макета

Макет по умолчанию сверху вниз:

  1. Область результата — прокручиваемая история диалога
  2. Разделитель
  3. Дополнительные виджеты — из _get_extra_tui_widgets()
  4. Строка состояния — модель, % контекста, прошедшее время
  5. Панель изображений — количество прикреплённых изображений.
  6. Область ввода — пользовательский запрос.
  7. Статус голоса — индикатор записи.
  8. Меню автодополнения — предложения автодополнения

Советы