Mở rộng CLI
Hermes hiển thị các móc mở rộng được bảo vệ trên HermesCLI để CLI trình bao bọc có thể thêm tiện ích, liên kết phím và tùy chỉnh bố cục mà không ghi đè phương thức run() hơn 1000 dòng. Điều này giúp tiện ích mở rộng của bạn tách biệt khỏi những thay đổi nội bộ.
Điểm mở rộng
Có năm đường nối mở rộng có sẵn:
| Móc | Mục đích | Ghi đè khi... |
|---|---|---|
_get_extra_tui_widgets() | Đưa các widget vào bố cục | Bạn cần một thành phần giao diện người dùng ổn định (bảng điều khiển, dòng trạng thái, trình phát mini) |
_register_extra_tui_keybindings(kb, *, input_area) | Thêm phím tắt | Bạn cần các phím nóng (bảng chuyển đổi, điều khiển vận chuyển, phím tắt phương thức) |
_build_tui_layout_children(**widgets) | Toàn quyền kiểm soát việc đặt hàng widget | Bạn cần sắp xếp lại hoặc bọc các vật dụng hiện có (hiếm) |
process_command() | Thêm lệnh gạch chéo tùy chỉnh | Bạn cần xử lý /mycommand (móc có sẵn) |
_build_tui_style_dict() | Kiểu tùy chỉnh của bộ công cụ nhắc nhở | Bạn cần màu sắc hoặc kiểu dáng tùy chỉnh (móc có sẵn) |
Ba cái đầu tiên là những cái móc được bảo vệ mới. Hai cái cuối cùng đã tồn tại.
Bắt đầu nhanh: trình bao bọc CLI
#!/usr/bin/env python3
"""my_cli.py — Example wrapper CLI that extends 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):
"""Add a toggleable info panel above the status bar."""
cli_ref = self
return [
Window(
FormattedTextControl(lambda: "📊 My custom panel content"),
height=1,
filter=Condition(lambda: cli_ref._panel_visible),
),
]
def _register_extra_tui_keybindings(self, kb, *, input_area):
"""F2 toggles the custom panel."""
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:
"""Add a /panel slash command."""
if cmd.strip().lower() == "/panel":
self._panel_visible = not self._panel_visible
state = "visible" if self._panel_visible else "hidden"
print(f"Panel is now {state}")
return True
return super().process_command(cmd)
if __name__ == "__main__":
cli = MyCLI()
cli.run()
Chạy nó:
cd ~/.hermes/hermes-agent
source .venv/bin/activate
python my_cli.py
Tham khảo móc
_get_extra_tui_widgets()
Trả về danh sách các tiện ích của bộ công cụ nhắc nhở để chèn vào bố cục TUI. Các tiện ích xuất hiện giữa miếng đệm và thanh trạng thái — phía trên khu vực đầu vào nhưng bên dưới đầu ra chính.
def _get_extra_tui_widgets(self) -> list:
return [] # default: no extra widgets
Mỗi tiện ích phải là vùng chứa bộ công cụ nhắc nhở (ví dụ: Window, ConditionalContainer, HSplit). Sử dụng ConditionalContainer hoặc filter=Condition(...) để chuyển đổi các tiện ích.
from prompt_toolkit.layout import ConditionalContainer, Window, FormattedTextControl
from prompt_toolkit.filters import Condition
def _get_extra_tui_widgets(self):
return [
ConditionalContainer(
Window(FormattedTextControl("Status: connected"), height=1),
filter=Condition(lambda: self._show_status),
),
]
_register_extra_tui_keybindings(kb, *, input_area)
Được gọi sau khi Hermes đăng ký tổ hợp phím của riêng mình và trước khi bố cục được xây dựng. Thêm tổ hợp phím của bạn vào kb.
def _register_extra_tui_keybindings(self, kb, *, input_area):
pass # default: no extra keybindings
Thông số:
kb— Phiên bảnKeyBindingscho ứng dụng nhắc_toolkitinput_area— Tiện íchTextAreachính, nếu bạn cần đọc hoặc thao tác với dữ liệu nhập của người dùng
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 "
Tránh xung đột với tổ hợp phím tích hợp: Enter (gửi), Escape Enter (dòng mới), Ctrl-C (ngắt), Ctrl-D (thoát), Tab (chấp nhận đề xuất tự động). Các phím chức năng F2+ và tổ hợp Ctrl nói chung là an toàn.
_build_tui_layout_children(**widgets)
Chỉ ghi đè điều này khi bạn cần toàn quyền kiểm soát thứ tự tiện ích. Thay vào đó, hầu hết các tiện ích mở rộng nên sử dụng _get_extra_tui_widgets().
def _build_tui_layout_children(self, *, sudo_widget, secret_widget,
approval_widget, clarify_widget, spinner_widget, spacer,
status_bar, input_rule_top, image_bar, input_area,
input_rule_bot, voice_status_bar, completions_menu) -> list:
Việc triển khai mặc định trả về:
[
Window(height=0), # anchor
sudo_widget, # sudo password prompt (conditional)
secret_widget, # secret input prompt (conditional)
approval_widget, # dangerous command approval (conditional)
clarify_widget, # clarify question UI (conditional)
spinner_widget, # thinking spinner (conditional)
spacer, # fills remaining vertical space
*self._get_extra_tui_widgets(), # YOUR WIDGETS GO HERE
status_bar, # model/token/context status line
input_rule_top, # ─── border above input
image_bar, # attached images indicator
input_area, # user text input
input_rule_bot, # ─── border below input
voice_status_bar, # voice mode status (conditional)
completions_menu, # autocomplete dropdown
]
Sơ đồ bố trí
Bố cục mặc định từ trên xuống dưới:
- Vùng đầu ra — cuộn lịch sử cuộc trò chuyện
- Khoảng cách
- Tiện ích bổ sung — từ
_get_extra_tui_widgets() - Thanh trạng thái — mô hình, % ngữ cảnh, thời gian đã trôi qua
- Thanh hình ảnh — số lượng hình ảnh đính kèm
- Khu vực nhập — lời nhắc của người dùng
- Trạng thái giọng nói — chỉ báo ghi âm
- Menu Hoàn thành — đề xuất tự động hoàn thành
Mẹo
- Vô hiệu hóa màn hình sau khi thay đổi trạng thái: gọi
self._invalidate()để kích hoạt vẽ lại bộ công cụ nhắc nhở. - Trạng thái tác nhân truy cập:
self.agent,self.model,self.conversation_historyđều khả dụng. - kiểu tùy chỉnh: Ghi đè
_build_tui_style_dict()và thêm mục nhập cho các lớp kiểu tùy chỉnh của bạn. - Lệnh gạch chéo: Ghi đè
process_command(), xử lý lệnh của bạn và gọisuper().process_command(cmd)cho mọi thứ khác. - Không ghi đè
run()trừ khi thực sự cần thiết — các móc mở rộng tồn tại đặc biệt để tránh sự ghép nối đó.