Hermes Telegram Dashboard 架構分析

生成日期:2026-06-28 分析範圍:/usr/local/lib/hermes-agent/ Telegram 相關模組 模式:Analysis Only(未修改任何程式)


1. 整體架構

┌─────────────────────────────────────────────────────────────┐
│  Telegram Server (Bot API)                                   │
└──────────────────────┬──────────────────────────────────────┘
                       │ Polling / Webhook
                       ▼
┌──────────────────────────────────────────────────────────────┐
│  TelegramAdapter (plugins/platforms/telegram/adapter.py)     │
│  ┌─────────────────────────────────────────────────────────┐ │
│  │ Application (python-telegram-bot)                       │ │
│  │  ├─ TelegramMessageHandler(TEXT) → _handle_text_message │ │
│  │  ├─ TelegramMessageHandler(COMMAND) → _handle_command   │ │
│  │  ├─ TelegramMessageHandler(LOCATION)                    │ │
│  │  ├─ TelegramMessageHandler(PHOTO/VIDEO/AUDIO/...)      │ │
│  │  └─ CallbackQueryHandler → _handle_callback_query      │ │
│  ├─ State (in-memory dicts):                               │ │
│  │  ├─ _model_picker_state: {chat_id → dict}               │ │
│  │  ├─ _approval_state: {message_id → session_key}         │ │
│  │  ├─ _slash_confirm_state: {confirm_id → session_key}    │ │
│  │  └─ _clarify_state: {clarify_id → session_key}          │ │
│  ├─ send_model_picker() — Inline Keyboard 模型選擇器        │ │
│  └─ _is_callback_user_authorized() — callback 權限驗證     │ │
└──────────────────────┬──────────────────────────────────────┘
                       │ MessageEvent
                       ▼
┌──────────────────────────────────────────────────────────────┐
│  GatewayRunner (gateway/run.py)                              │
│  _handle_message(event)                                      │
│   ├─ pre_gateway_dispatch plugin hook                        │
│   ├─ user auth / pairing flow                                │
│   ├─ resolve_command() → GatewaySlashCommandsMixin           │
│   │   └─ /new /stop /status /restart /clear ...              │
│   └─ _handle_message_with_agent() → Agent conversation loop  │
└──────────────────────────────────────────────────────────────┘

2. 關鍵檔案

檔案責任行數
plugins/platforms/telegram/adapter.pyTelegram 適配器(接收、發送、Handler 註冊)7798
hermes_cli/telegram_managed_bot.pyBot onboarding(Managed Bot 配對)358
plugins/platforms/telegram/telegram_ids.pyChat ID 正規化51
plugins/platforms/telegram/telegram_network.pyFallback IP 傳輸(DNS 失靈時)259
gateway/run.pyGatewayRunner 核心(訊息分派、agent 對話)18791
gateway/slash_commands.pySlash command 處理器(/new, /stop, /status 等)4118
gateway/platforms/base.pyBasePlatformAdapter 抽象層5351
gateway/config.pyPlatformConfig(token 等設定)2076
hermes_cli/commands.pyCOMMAND_REGISTRY、選單、resolve_command2048
tools/send_message_tool.py跨平台發送工具(含 MEDIA)1373+

3. 核心元件定位

Telegram Bot 入口

  • 位置adapter.py:2310async def connect()
  • 流程Application.builder().token(self.config.token) → 註冊 handlers → app.start() → polling/webhook

Bot Token 載入

  • 位置adapter.py:2339self.config.token
  • 來源gateway.yaml → platforms.telegram.token 或環境變數 TELEGRAM_BOT_TOKEN
  • 型別PlatformConfig.tokengateway/config.py:331

Message Handler

  • 位置adapter.py:2481-2498
  • 5 個 TelegramMessageHandler
    • TEXT & ~COMMAND_handle_text_message
    • COMMAND_handle_command
    • LOCATION | VENUE_handle_location_message
    • PHOTO | VIDEO | AUDIO | VOICE | Document.ALL | Sticker.ALL_handle_media_message

Command Handler

  • 位置adapter.py:6582_handle_command()
  • 流程:收到命令 → 轉發給 GatewayRunner → resolve_command()GatewaySlashCommandsMixin 處理

Callback Handler

  • 位置adapter.py:4456_handle_callback_query()
  • 已存在的 callback 協議
Prefix用途說明
mp:Model picker模型選擇器
mpg: / mm: / mc: / mb / mx / mg:Model picker 子操作翻頁、分組等
gt:Gmail triageGmail 郵件分類
ea:Exec approval危險命令批准(once/session/always/deny)
sc:Slash confirm/reload-mcp 等確認提示
cl:Clarify多選題 clarify 工具

Telegram API Library

  • 使用python-telegram-bot
  • 匯入from telegram import Update, Bot, Message, InlineKeyboardButton, InlineKeyboardMarkup
  • 擴展from telegram.ext import Application, CommandHandler, CallbackQueryHandler, MessageHandler, ContextTypes, filters

Router 架構

  • 模式python-telegram-botApplication.add_handler() 模式
  • 每種 filter 一個 handler,按註冊順序匹配
  • Callback 統一入口:所有 inline keyboard 點擊都走 _handle_callback_query(),內部用前綴分流

4. 現有功能清單

功能狀態位置
Inline Keyboard✅ 已存在send_model_picker() at line 3967
Callback Query✅ 已存在_handle_callback_query() at line 4456
Menu System✅ 已存在telegram_menu_commands() at line 889,最多 100 個 BotCommand
State Machine❌ 不存在只有 4 個獨立 dict
Dashboard❌ 不存在
權限驗證✅ 已存在_is_callback_user_authorized()
Fallback Transport✅ 已存在TelegramFallbackTransport(DNS 失靈時用 IP 直連)
Webhook 模式✅ 已存在TELEGRAM_WEBHOOK_URL env 控制
Forum Topic 支援✅ 已存在_ensure_forum_commands() 懶加載
Media 處理✅ 已存在Photo/Video/Audio/Voice/Document/Sticker 全支援
Reaction✅ 已存在_set_reaction() / _clear_reactions()

5. Dashboard v1 最佳架構建議

建議檔案結構

plugins/platforms/telegram/
├── adapter.py              ← 現有(只加 1 行)
├── telegram_dashboard.py   ← 新增:Dashboard 核心
│   ├─ DashboardMenu       — 選單樹(Main → Sub-menus)
│   ├─ DashboardState       — State Machine(取代 dict)
│   └─ DashboardRenderer    — 訊息格式化 + InlineKeyboard 產生
├── telegram_states.py      ← 新增:State Machine + callback routing
└── telegram_menu.py        ← 新增:指令擴展(/dashboard, /cron, /sessions 視覺化)

State Machine 設計

class DashboardState(Enum):
    IDLE = "idle"
    MAIN_MENU = "main"
    SESSION_LIST = "session_list"
    SESSION_DETAIL = "session_detail"
    CRON_LIST = "cron_list"
    CRON_DETAIL = "cron_detail"
    CONFIG = "config"
    SKILL_LIST = "skill_list"

Dashboard Callback 協議

Prefix用途現有
d:Dashboard navigation(menu/submenu/select)❌ 新增
db:Dashboard button action(back/refresh/execute)❌ 新增
mp:Model picker✅ 現有
ea:Approval✅ 現有
sc:Slash confirm✅ 現有
cl:Clarify✅ 現有

需修改的現有檔案

  1. adapter.py — 只加 dashboard callback 前綴判斷(在 _handle_callback_query() 開頭加 if data.startswith("d:")db:
  2. hermes_cli/commands.py — 新增 /dashboard 指令,觸發 telegram_dashboard.py 發送主選單

建議新增的檔案

檔案預估行數內容
telegram_dashboard.py~300Dashboard 核心邏輯:選單樹、狀態轉換、資料獲取
telegram_states.py~80State Machine 資料結構:DashboardState enum + 轉換表
telegram_menu.py~150InlineKeyboard 選單產生器:主選單、工作階段列表、Cron 列表等

設計原則

  1. 不動 adapter.py 核心 — 避免 7798 行檔案更動風險
  2. 複用現有 callback 模式d: 前綴沿用 mp:/ea: 已驗證的 routing 慣例
  3. State Machine 替換散落的 dict — 目前 4 個獨立 dict 難維護;Dashboard 需要清晰的生命週期管理
  4. hermes_cli/commands.py 整合/dashboard 指令可直接從 Telegram 觸發
  5. 向後相容 — 原有 callback 協議(model picker、approval)完全不受影響

6. 相關節點