调试与排错
看日志
插件在 Hermes 自身日志管线之外,额外用了一套 OpenClaw 风格的文件日志,按天写在:
~/.yoooclaw/plugins/yoooclaw-hermes/logs/YYYY-MM-DD.logYOOOCLAW_HERMES_LOG_DIR 可以覆盖日志目录。稳定版会在写文件、以及把记录交给 Hermes 上游日志 handler 之前,脱敏常见的密钥、用户文本、用户 URL、邮箱、手机号、bearer token、JWT 和长十六进制 token;版本号里带 beta 的构建会保留原始日志,方便调试(和 OpenClaw 插件的行为一致)。排错时要留意:脱敏可能把真正出问题的那个值(比如 api-key 的某个片段)也一起遮住了,需要看原始值时确认插件版本号是否带 beta。超过 30 天的日志会自动清理,用 YOOOCLAW_HERMES_LOG_RETENTION_DAYS 调整保留天数。
通过 Hermes 插件 CLI 检索日志:
hermes yoooclaw logs --keyword relay --from 2026-06-01 --to 2026-06-04 --limit 50Hermes 托管的前台 daemon 子进程的 stdout/stderr 单独写在:
~/.yoooclaw/hermes-plugin/daemon-fg.log自更新安装日志单独存放:<state_root>/hermes-plugin/update/update.log,退出码在同目录的 exit_code 文件里。
Lifecycle 诊断
升级或连接异常时,先看 lifecycle 状态:
hermes yoooclaw lifecycle status重点看当前 daemon 是否宣称 owner=hermes-plugin 且 ingressMode=proxied,以及 generation 是否匹配当前插件版本 / profile / Relay environment / api-key。不匹配时插件本该自动重启服务组;如果没有,手动触发一次:
hermes yoooclaw lifecycle restartgeneration 是插件版本、内置 CLI 二进制哈希、当前 profile、Relay environment、Relay URL、api-key 指纹、ingress 模式和本地 egress callback URL 一起算出的 SHA-256。任何一项变化都会让 generation 对不上,触发插件接管/重启。
lifecycle status 里的 status 字段有三种取值,含义不同:
| 状态 | 含义 | watchdog 行为 |
|---|---|---|
mismatch | daemon 存在但 owner/generation/ingressMode 对不上,或 daemon 根本没有 lifecycle 元数据(比如用户手动执行了 yc daemon start) | 触发接管重启 |
unknown | daemon status 探测本身失败(不是"未运行",是探测不到结果) | 视为可容忍的瞬时噪音,不会立即重启,需要连续出现达到 YOOOCLAW_HERMES_LIFECYCLE_MISMATCH_STREAK(默认 2 次)门槛 |
| daemon 子进程意外退出 | watchdog 检测到自己拥有的进程 exit,绕过 mismatch-streak 阈值 | 立即重启整个服务组(区别于用户主动 daemon stop 的预期退出,靠内部 _owned_process_seq 计数区分) |
环境与 Relay 排查
hermes yoooclaw env # 当前 profile + Relay 状态
yoooclaw auth show # api-key 是否就位(与插件共享 credentials.json)
yoooclaw tunnel status # 底层 CLI 视角的隧道连接状态因为 daemon 以 --ingress proxied 跑在 Hermes 里,它自己不开 Relay 隧道,tunnel status 看到的是本地 sidecar 视角;实际的 openclaw-service 连接由插件的 OpenClawRelayTransport 维护,状态以 lifecycle status 和插件日志为准,不要只看 CLI 侧的隧道状态就判断连接是否正常。
PHONE_NOTIFICATIONS_ENV 解析优先级:显式设置的环境变量 > 当前 profile 的 relay host(若 CLI 版本 ≥ 0.2.4,会读取该变量并覆盖内置默认 host) > 兜底 production。传了一个未知值不会报错,会静默回落到 production——如果发现环境切换「看起来没生效」,先确认变量拼写。
常见错误信息对照
以下是插件代码里会抛出的原始错误信息(含 code),可以直接拿关键字去日志或对话里搜:
| 错误信息 | code | 触发场景 | 处理 |
|---|---|---|---|
Embedded YoooClaw CLI is not available for <os>/<arch>. | YOOOCLAW_CLI_UNSUPPORTED_PLATFORM | 当前平台没有内置的 CLI 二进制(仅支持 darwin-arm64/x64、linux-arm64/x64、win32-x64) | 确认运行平台是否受支持 |
Embedded CLI binary is missing: <path>. | YOOOCLAW_CLI_BINARY_MISSING | 内置二进制文件丢失 | 重新安装插件 |
Embedded CLI checksum mismatch: <path>. | YOOOCLAW_CLI_CHECKSUM_MISMATCH | 内置二进制被篡改或安装损坏 | 见下文「CLI 校验和不匹配」 |
YoooClaw CLI timed out after <n>s. | YOOOCLAW_CLI_TIMEOUT | 调用内置 CLI 子进程超时 | 检查 daemon 是否卡死,或加大超时 |
Could not find \yc`, `yoooclaw` in PATH.` | YOOOCLAW_CLI_NOT_FOUND | PATH 里既没有内置 shim 也没有本地开发环境的 yc/yoooclaw | 检查 YOOOCLAW_HERMES_INSTALL_CLI 是否被设为 0,或 YOOOCLAW_CLI_PATH 指向了不存在的路径 |
YoooClaw daemon did not become ready within <n>s | — | daemon 子进程在 ready_timeout_seconds(默认 25s)内没有就绪,会被强制终止,避免进程泄漏 | hermes yoooclaw lifecycle status 看 daemon.lastError,通常是端口占用或宿主环境异常 |
YoooClaw daemon did not reach the expected proxied lifecycle | — | daemon 起来了但没能进入 proxied ingress 模式 | 结合 daemon 日志排查,通常是配置或端口冲突 |
YoooClaw openclaw-service Relay api-key is missing | — | 没有配置 api-key 就尝试连接 Relay | yoooclaw auth set-default-api-key |
YoooClaw openclaw-service Relay authentication failed label=... : ... Update ~/.yoooclaw/credentials.json and reconnect. | — | api-key 被拒绝(401/403/4401/invalid apikey),不会无限静默重试 | 更新 credentials.json 里对应的 key,仅靠自动重连解决不了 |
Timed out connecting to YoooClaw openclaw-service Relay | — | 握手阶段超时 | 检查网络连通性 |
YoooClaw Relay is disconnected / openclaw-service Relay is disconnected | — | 尝试在没有已连接隧道时发送帧 | 等待重连,或手动 lifecycle restart |
No active YoooClaw APP route for chat <id> | — | 目标 APP 会话没有对应的活跃连接 | 确认 APP 端是否在线 |
YoooClaw egress callback server is not running | — | egress callback 本地 HTTP 服务未启动就被访问 | 通常是内部时序问题,lifecycle restart |
YoooClaw daemon is not running / YoooClaw daemon status did not include a port | — | daemon 桥接层找不到可用的 daemon | 先确认 daemon 本身状态 |
更新未执行:需要用户在对话中明确同意后,以 confirm=true 调用。 | YOOOCLAW_UPDATE_NOT_CONFIRMED | 模型调用更新工具时没有传 confirm=true | 需要在对话里明确同意后再次调用 |
当前插件是开发(editable/源码树)安装,拒绝自动更新;请在插件仓库里手动升级。 | YOOOCLAW_UPDATE_EDITABLE_INSTALL | 插件是 pip install -e 的可编辑安装 | 手动在源码树里升级,不要走自更新 |
已有更新正在进行(目标版本 ...),请等待其完成。 | YOOOCLAW_UPDATE_IN_PROGRESS | 已有一次更新在跑 | 等待完成;如果 pending.json 已经超过超时时间(默认 1800s)仍未清除,会被视为「陈旧」并自动放行新的更新 |
目标版本号不合法:<v> | YOOOCLAW_UPDATE_BAD_VERSION | 传入的版本号格式不对 | 检查版本号格式 |
当前版本 ... 已不低于目标版本 ...,无需更新。 | YOOOCLAW_UPDATE_NOT_NEWER | 目标版本不比当前版本新 | 无需操作 |
下载安装器失败:<error> | YOOOCLAW_UPDATE_INSTALLER_FETCH_FAILED | 从 OSS 拉取安装脚本失败 | 检查网络,或稍后重试 |
启动更新进程失败:<error> | YOOOCLAW_UPDATE_SPAWN_FAILED | 启动更新子进程失败 | 检查权限与磁盘空间 |
常见症状 → 处理
hermes plugins enable yoooclaw 报错找不到插件
Hermes 0.15.1 及更早版本的 plugins enable/disable/list 只认目录形式插件,不扫描 Python entry points。直接编辑 ~/.hermes/config.yaml:
plugins:
enabled: [yoooclaw, yoooclaw_app]再 hermes gateway restart。一键安装器已经自动写好这一步,只有手动 pip install 时才需要自己处理。
安装器报「Hermes 版本过低」直接中止
需要 Hermes Agent >= 0.14.0,因为 APP 适配器依赖的 PluginContext.register_platform 平台 API 更早版本没有。先升级 Hermes(hermes update),再重新跑安装器 —— 这是设计如此的硬性检查,不是安装器 bug。
安装器报「无法确定 Hermes 的 Python 环境」
安装器会尝试若干标准路径寻找 Hermes 使用的 venv Python,找不到就直接拒绝安装(不会装进一个通用 Python 环境,避免 gateway 之后 import 不到插件)。报错会列出它尝试过的路径。解决办法三选一:设置 HERMES_HOME;把 Hermes 自带的 hermes 命令加进 PATH;或者直接用 --python /path/to/hermes-agent/venv/bin/python 显式指定。
安装器报「Python 版本过低」
yoooclaw-hermes-plugin 要求 Python ≥ 3.11。检查 Hermes 使用的 venv 是用什么 Python 版本创建的,必要时重建 venv。
CLI 校验和不匹配(YOOOCLAW_CLI_CHECKSUM_MISMATCH)
内置 CLI 二进制文件的哈希和插件包内 manifest.json 记录的不一致,通常是安装包损坏或文件被意外改动。插件会先尝试回退到之前缓存过的安装(按 mtime 取最新一份),如果没有可用的缓存就保持 PATH 不变(此时命令会报 YOOOCLAW_CLI_NOT_FOUND)。彻底解决需要重新安装插件。
APP 连不上 / 会话没反应
按顺序确认:
yoooclaw auth show—— account 级 api-key 已配置,且和插件共享同一份~/.yoooclaw/credentials.json;- 环境变量里没有残留的
YOOOCLAW_APP_API_KEY/YOOOCLAW_API_KEY/YOOOCLAW_APP_ALLOWED_USERS/YOOOCLAW_APP_ALLOW_ALL_USERS/ 已废弃的YOOOCLAW_APP_RELAY_URL(安装器每次安装都会从~/.hermes/.env里清掉这几个,但手动改过环境变量的话要自己查); hermes yoooclaw lifecycle status—— daemon owner/generation/ingressMode 都对得上;- 插件日志里
--keyword relay看有没有连接错误; - 如果报的是
chat.send is only allowed for yoooclaw_app sessions,说明目标 session 不属于yoooclaw_app—— 插件对跨渠道的chat.send会直接拒绝,不是 bug; - 多设备场景下,同一个 api-key 的所有连接会收到同一条广播,每个 Hermes 实例各自处理一次,可能导致重复的响应帧——如果看到「同一条消息回复了两次」,先确认是不是跑了多个 Hermes 实例共用同一把 key。
Relay websocket 反复断开
适配器自带 watchdog:断连超过 YOOOCLAW_HERMES_WS_RESTART_AFTER(默认 30s)会自动重启服务组(短暂网络抖动不会触发整组重启),失败按指数退避重试(上限 YOOOCLAW_HERMES_LIFECYCLE_MAX_BACKOFF,默认 60s)。断连期间产生的 egress 事件(如 recording.status)会先缓冲(上限 100 条,TTL 60s,过期丢弃),重连后按顺序补发,不会丢最近的事件。如果一直卡在重连,通常是网络问题或 api-key 失效(401/403/4401/invalid apikey 都会快速失败而不是无限静默重试),而不是 watchdog 本身的问题;先用 yoooclaw auth show 确认 key 没过期。
如果重连一直失败但本地 daemon 是好的,watchdog 会独立恢复本地 daemon 并持续重试远端连接,不会出现「WS 断了、daemon 也被连带停掉」的死状态。
升级后插件行为没变 / skills 没更新
~/.hermes/skills/yoooclaw/ 是插件安装时复制进去的(不是软链接,因为 Hermes 不信任 site-packages 路径),带一个 .yoooclaw-managed 标记。如果这个目录已经存在但不是插件创建的(没有该标记),插件会打一条警告日志然后跳过覆盖,不会强制替换用户自己放的内容。升级后发现 skills 没更新,先检查这个目录是不是被手动改动过。
更新卡住 / 更新完没收到通知
自更新是异步的:旧进程里的 watcher 线程会持续把 update.log 流式推送到最后一次交互的 APP 会话,直到 exit_code 文件出现或超过超时时间(默认 1800s,超时按退出码 124 处理)。hermes gateway restart 由安装脚本自己触发,重载后的新插件进程会调用 resume_after_reload(),通过原子改名 pending.json → pending.claimed.json 保证新旧进程不会同时各发一次通知。如果长时间没反应,看 <state_root>/hermes-plugin/update/update.log 和同目录下的 exit_code 文件确认实际状态。
卸载插件
仓库里没有专门的卸载脚本。需要卸载时执行 pip uninstall yoooclaw-hermes-plugin,再手动从 ~/.hermes/config.yaml 的 plugins.enabled 里移除 yoooclaw 和 yoooclaw_app,然后重启 gateway。