让 Hermes 说人话:把英文系统提示就地换成随机中文(忙时回执/进度心跳/自主进化复盘/后台任务/超时/权限/接口报错…),三层网覆盖,词库 106 类 672 条。
|
|
1 dienu atpakaļ | |
|---|---|---|
| bin | 1 dienu atpakaļ | |
| .gitignore | 1 dienu atpakaļ | |
| CHANGELOG.md | 1 dienu atpakaļ | |
| LICENSE | 1 dienu atpakaļ | |
| README.md | 1 dienu atpakaļ | |
| __init__.py | 1 dienu atpakaļ | |
| package.json | 1 dienu atpakaļ | |
| phrases.json | 1 dienu atpakaļ | |
| plugin.yaml | 1 dienu atpakaļ | |
| validate_phrases.py | 1 dienu atpakaļ |
让 Hermes 说人话。 把 Hermes 和工具吐出来的英文系统提示,就地换成随机的日常中文—— 同一种情况每次说法都不一样,消息看着不像机器。
适用于 Hermes Agent。词库 106 类 / 672 条中文候选。
Hermes 本体没有 i18n。config.yaml 里的 language / locale / 顶层 system_prompt 都没人读,
运行时硬编码的英文只能从消息出口改。
唯一官方支持的例外是 display.status_phrases + $HERMES_HOME/status_phrases.yaml,
但它只覆盖长任务心跳这类表面;其余全靠本插件。
| 原来(英文) | 换成(随机一条) |
|---|---|
⚡ Interrupting current task (3 min elapsed). I'll respond shortly. |
收到!先按下暂停键,马上看你这条。 (跑了 3 分钟) |
⏳ Queued for the next turn. I'll respond once the current task finishes. |
手头这摊还没收工,你这条我收好了,一腾出手就办。 |
⏩ Steered into current run. Your message arrives after the next tool call. |
收到,你这条我捎在手上了,下一步就按它走。 |
↪ Redirected current run. I'll adjust using your correction. |
好,方向调过来了,按你的纠正走。 |
⏳ Working — 12 min — running: browser_exec |
还在跑,12 分钟了——稳住,就快出结果了。 — 此刻在干:browser_exec |
💾 Self-improvement review: Memory updated · Skill 'x' patched |
💾 这一轮的修行成果:🧠 这段我刻进记忆里了。 · 🔧 「x」又精进了一点。 |
⚠️ No reply: the request was cancelled by a new correction on every attempt… |
⚠️ 它没回话: 你连着改了几次方向,每次都把这一轮打断了。我不硬撑了——你最后那条纠正已在队列里,下一步就照它走。 |
⚠️ Hermes is shutting down — your current task will be interrupted… |
⚠️ 我要下线一会儿——手上这个任务会中断。等我回来,你随便说句话,我就接着往下做。 |
Cronjob Response: 每日额度日报 |
📬 定时任务「每日额度日报」的结果: |
Permission denied |
这条路没权限——不硬闯,我换条道走。 |
[Command timed out after 60s] |
等了 60 秒还没动静,先掐了。 |
Traceback (most recent call last): |
程序崩了一下,堆栈如下。 |
| 层 | 手段 | 覆盖 |
|---|---|---|
| 1 | transform_tool_result |
工具结果(超时、权限、路径、接口报错…) |
| 2 | transform_llm_output |
助手最终回复 |
| 3 | 包住适配器的出站方法 | 网关自己发到聊天的通知 |
第 3 层是关键。 忙时回执、进度心跳、自主进化复盘、后台任务收工、cron 投递……
源码里是直接 adapter.send(...) 发出去的,不经过任何插件钩子。只做 1+2 的话,
聊天里看到的还是英文——这就是「装了插件却没生效」的真因。
第 3 层具体包了每个平台适配器(含子类)的 22 个发文本方法:send / edit_message /
send_stream_frame / send_private_notice / send_slash_confirm / send_clarify /
send_exec_approval / send_image(caption) / send_document / send_voice / send_video /
emit_warning / send_final_ledgered …,以及「返回值即文本」的 _format_exec_approval。
位置参数和关键字参数都兜住,一个方法里有多个文本参数(title + message)也一并处理。
npx plugin-tips-cn # 装到 $HERMES_HOME/plugins/plugin-tips-cn
hermes plugins enable plugin-tips-cn # 启用
# 然后重启一次网关
cp -r plugin-tips-cn "$HERMES_HOME/plugins/"
hermes plugins validate "$HERMES_HOME/plugins/plugin-tips-cn"
hermes plugins enable plugin-tips-cn
git clone https://git.fmode.cn/fmode/plugin-tips-cn.git "$HERMES_HOME/plugins/plugin-tips-cn"
hermes plugins enable plugin-tips-cn
必须重启一次网关:插件在进程启动时 discovery 一次,长驻进程不会自动重扫。 容器里由 s6 托管的网关,杀掉进程会自动拉起。
只改 phrases.json——按 mtime 热加载,改完立刻生效。只有改 .py / plugin.yaml 才要重启网关。
{
"id": "cmd_timeout", // 类别 id
"label": "命令超时", // 给人看的说明
"patterns": ["\\[Command timed out after (?P<n>\\d+)s\\]"], // 正则,忽略大小写,可用命名组
"variants": ["等了 {n} 秒还没动静,先掐了。", "..."] // 命中时随机挑一条,想加多少加多少
}
改完跑一遍自检:
python3 validate_phrases.py
它会拦下四类静默 bug:JSON 不合法、正则编译失败、候选用 {n} 而正则组名叫 code
(这种错不会报异常,只会在运行时把字面量 {n} 发给用户)、类别缺 patterns/variants。
| 环境变量 | 作用 |
|---|---|
PLUGIN_TIPS_CN_DISABLE=1 |
整个插件静默(默认开) |
PLUGIN_TIPS_CN_LOG=1 |
每次替换打一条日志,方便调试 |
PLUGIN_TIPS_CN_NO_SEND=1 |
只关掉「适配器出口」那一层 |
插件会连你自己的工具输出一起汉化,所以验证脚本打印的「原文」会被换掉、看着像没生效。
把空格换成 · 再打印就能绕过(正则匹配不上):
print(out.replace(" ", "·"))
端到端自检:
echo "⚡ Interrupting current task. I'll respond to your message shortly."
# 读回来是中文就说明网关里的插件在跑
验证第 3 层是否装上了:看网关日志里有没有
plugin-tips-cn: 已包住 N 个适配器出站方法(覆盖 M 个类)
"exit_code": 124),只替换自然语言句子MIT