第十一章 配置与 Profile 系统
Hermes 的配置系统看似简单(一个 YAML + 一个 .env),但背后是精心设计的版本迁移机制和多实例隔离方案。
11.1 配置体系
DEFAULT_CONFIG
hermes_cli/config.py 中定义了所有配置项的默认值:
python
DEFAULT_CONFIG = {
"model": "anthropic/claude-opus-4.6",
"display": {
"skin": "default",
"tool_progress": True,
"background_process_notifications": "all",
},
"context": {
"engine": "builtin",
"compression_threshold": 0.8,
},
"memory": {
"provider": "builtin",
"nudge_interval": 5,
},
"_config_version": 5, # 配置版本号
}OPTIONAL_ENV_VARS
每个环境变量都有元数据描述:
python
OPTIONAL_ENV_VARS = {
"OPENROUTER_API_KEY": {
"description": "OpenRouter API key for 200+ models",
"prompt": "OpenRouter",
"url": "https://openrouter.ai/keys",
"password": True,
"category": "provider", # provider / tool / messaging / setting
},
"TELEGRAM_BOT_TOKEN": {
"description": "Telegram bot token",
"prompt": "Telegram Bot",
"url": "https://t.me/BotFather",
"password": True,
"category": "messaging",
},
}多个配置加载器
| 加载器 | 使用场景 | 位置 |
|---|---|---|
load_cli_config() | CLI 模式 | cli.py |
load_config() | hermes tools、hermes setup | hermes_cli/config.py |
| 直接 YAML 加载 | 网关模式 | gateway/run.py |
11.2 配置版本迁移
当新版本添加或修改配置项时,通过 _config_version 递增触发迁移:
迁移示例
python
def _migrate_v4_to_v5(config):
"""v4 → v5: 新增 memory.nudge_interval"""
if "memory" not in config:
config["memory"] = {}
if "nudge_interval" not in config["memory"]:
config["memory"]["nudge_interval"] = 5
config["_config_version"] = 5
return config关键设计:迁移是递增式的(v1→v2→v3→...),不是直接跳到最新版本。这确保了从任何旧版本都能正确升级。
11.3 Profile 多实例
核心机制
_apply_profile_override() 在 hermes_cli/main.py 中设置 HERMES_HOME:
python
def _apply_profile_override(profile: str = None):
if profile:
home = Path.home() / ".hermes" / "profiles" / profile
home.mkdir(parents=True, exist_ok=True)
os.environ["HERMES_HOME"] = str(home)执行时机:在所有模块导入之前,确保 get_hermes_home() 返回正确的路径。
两条路径规则
python
# 代码路径(写入文件、数据库等)
from hermes_constants import get_hermes_home
config_path = get_hermes_home() / "config.yaml" # ✅ 正确
# 用户展示路径(日志、提示信息)
from hermes_constants import display_hermes_home
print(f"Config saved to {display_hermes_home()}/config.yaml") # ✅ 正确网关 Token 锁
不同 Profile 使用同一平台时(如两个 Telegram bot),需要防止冲突:
python
# gateway/status.py
def acquire_scoped_lock(token: str):
"""防止两个 Profile 使用相同的 bot token"""
...
def release_scoped_lock(token: str):
...11.4 斜杠命令注册中心
COMMAND_REGISTRY 是单一数据源,所有消费者都从它派生:
CommandDef 结构
python
CommandDef(
name="background", # 规范名(无斜杠)
description="Toggle background mode",
category="Session", # Session / Configuration / Tools / Info / Exit
aliases=("bg",), # 别名
args_hint="[prompt]", # 参数提示
cli_only=False, # 是否仅 CLI
gateway_only=False, # 是否仅网关
gateway_config_gate=None, # 配置门控:当配置值为 truthy 时在网关可用
)添加命令只需两步
- 在
COMMAND_REGISTRY中添加CommandDef - 在
cli.py的process_command()中添加处理逻辑
别名、帮助文本、Telegram 菜单、Slack 映射、自动补全全部自动更新。
11.5 皮肤/主题系统
hermes_cli/skin_engine.py 实现了数据驱动的 CLI 主题系统:
可定制项
| 元素 | 配置键 | 示例 |
|---|---|---|
| Banner 边框颜色 | colors.banner_border | #FFD700 |
| Spinner 表情 | spinner.thinking_faces | [🤔, 😌, 😊] |
| Spinner 动词 | spinner.thinking_verbs | [思考中, 处理中] |
| Spinner 翅膀 | spinner.wings | [[⟨⚡, ⚡⟩]] |
| 工具前缀 | tool_prefix | ┊ |
| 工具表情映射 | tool_emojis | {terminal: 💻, file: 📄} |
| Agent 名称 | branding.agent_name | Hermes |
| 欢迎语 | branding.welcome | Hello! |
内置皮肤
| 皮肤 | 风格 |
|---|---|
default | 经典 Hermes 金色/可爱 |
ares | 深红/铜色战神主题 + 自定义翅膀 |
mono | 灰度单色极简 |
slate | 冷蓝开发者主题 |
用户自定义皮肤
创建 ~/.hermes/skins/cyberpunk.yaml:
yaml
name: cyberpunk
description: 霓虹终端主题
colors:
banner_border: "#FF00FF"
banner_title: "#00FFFF"
banner_accent: "#FF1493"
spinner:
thinking_verbs: ["jacking in", "decrypting", "uploading"]
wings:
- ["⟨⚡", "⚡⟩"]
branding:
agent_name: "Cyber Agent"
response_label: " ⚡ Cyber "通过 /skin cyberpunk 或 display.skin: cyberpunk 激活。
源码导航:
- 配置定义 →
hermes_cli/config.py - 命令注册 →
hermes_cli/commands.py - 皮肤引擎 →
hermes_cli/skin_engine.py - Profile →
hermes_cli/main.py
下一章:第十二章 定时任务与自动化