跳转到内容

01 - 项目架构与模块依赖链

学习目标

本章聚焦 Hermes Agent 的顶层架构与模块依赖关系。你将了解:

  • 工具注册的导入链如何实现自动发现
  • 核心巨型模块的职责划分
  • CLI 界面的 Rich + prompt_toolkit 架构
  • 数据驱动的 Skin 引擎如何扩展

前置知识

本章涉及 Agent 架构的通用原理,建议先阅读:

下文直接聚焦 Hermes 的工程实现。


项目实践

文件依赖链:自底向上的自动注册

关键机制model_tools.py 在模块加载时调用:

  • discover_builtin_tools():使用 AST 解析找到所有 registry.register(...) 调用,按需 import 工具文件
  • discover_plugins()(try/except 包裹):发现 bundled / user / project / pip entry-point 四类插件

导入时序陷阱discover_plugins() 作为 model_tools.py 导入的副作用运行。不导入 model_tools.py 的代码路径无法看到插件工具。入口文件(run_agent.pycli.pygateway/run.py 等)都直接 import model_tools.py,确保工具发现被触发。

核心巨型模块

Hermes 选择将核心逻辑集中在少数大型文件中,而非拆分为大量微模块:

文件行数职责
run_agent.py~4410AIAgent 核心类:对话循环、预算、中断、压缩
cli.py~15089HermesCLI 编排器:Rich 面板 + prompt_toolkit 输入 + 动画
gateway/run.py~18556消息网关:平台路由、会话管理、命令分发
hermes_state.py数百行SQLite SessionDB + FTS5 全文搜索
hermes_constants.py数十行Profile 感知路径配置
hermes_logging.py数十行Profile 感知日志

设计逻辑:核心逻辑集中减少了跨模块依赖追踪的成本。通过 registry 和插件系统实现解耦,而非通过文件拆分。

CLI 界面架构

cli.py 的依赖链:

Rich 面板(输出渲染)
prompt_toolkit(交互式输入)
KawaiiSpinner(动画组件)
KawaiiSpinner 状态反馈(皮肤引擎驱动)

CLI 使用 Rich 进行富文本输出(颜色、表格、进度条),prompt_toolkit 处理用户输入(补全、历史、键绑定)。KawaiiSpinner 是自定义的终端动画组件,由皮肤引擎驱动颜色和样式。

数据驱动 Skin 引擎

hermes_cli/skin_engine.py(927 行)实现了数据驱动的主题系统:

内置皮肤(9 种)

皮肤风格
default金色/kawaii
ares红铜色战神
mono灰度
slate冷蓝
daylight亮色主题
warm-lightmode暖色亮色
poseidon海洋蓝
sisyphusaustere 灰度
charizard火山橙

用户皮肤~/.hermes/skins/<name>.yaml 放置即用,自动覆盖同名内置皮肤。

SkinConfig 数据类:name、description、colors、spinner、branding、tool_prefix、tool_emojis、banner_logo、banner_hero。

激活方式:/skin <name> CLI 命令或 display.skin 配置项。


问题与规避

巨型模块的维护成本

问题:15000+ 行的 cli.py 和 18000+ 行的 gateway/run.py 难以导航和理解。

对策:通过内部函数分组和类型注解保持可读性。核心逻辑通过 registry 和插件系统解耦,巨型文件主要承担编排职责而非实现细节。

皮肤缺失导致回退

问题:配置了不存在的皮肤名称,导致颜色方案回退到默认。

对策:皮肤引擎在皮肤缺失时 fallback 到 default,并以 WARNING 级别记录日志。


设计取舍

巨型模块 vs 微模块拆分

方案优势代价
巨型模块(Hermes)减少跨文件跳转、依赖关系清晰、import 链简单文件过大难以导航、合并冲突概率高
微模块拆分职责清晰、易于测试模块间依赖复杂、import 链难以追踪

Hermes 选择巨型模块是因为其目标用户是独立开发者和小型团队,代码可读性主要通过函数分组和类型注解实现,而非文件拆分。


参考来源

  • 源码验证:tools/registry.pymodel_tools.pyrun_agent.pycli.pyhermes_cli/skin_engine.pyAGENTS.md