Skip to content

Latest commit

 

History

History
212 lines (133 loc) · 6.86 KB

File metadata and controls

212 lines (133 loc) · 6.86 KB

技术文档:Hermes 联调关键发现与工程实践(面向开源社区)

日期:2026-02-13
目标:沉淀 Telegram ↔ OpenClaw ↔ OpenCode 联调中的高价值发现,提供可复用的实现与排障参考。

1. 概览

本文聚焦三类问题:

  1. 会话卡住(Queue 不前进)
  2. invalid api key 与 provider 线路错配
  3. Question Tool 远程回答的“无 hack”官方实现

核心产出:

  1. 明确了 Queue 卡住的可复现根因链。
  2. 明确了 MiniMax 双线路配置边界(minimaxi.com vs minimax.io)。
  3. 实测验证并落地了 OpenCode 官方 /question API 回传闭环。

2. 环境与版本

  1. OpenCode: 1.1.53
  2. OpenClaw: Hermes 网关模式(Telegram 群组接入)
  3. 关键目录:
    • 仓库:/Users/napstablook/.config/opencode/HERMES
    • 运行插件:/Users/napstablook/.config/opencode/plugins
    • OpenClaw 运行映射:/Users/napstablook/.config/opencode/workspace-hermes

3. 关键发现(按影响优先级)

3.1 Queue 卡住的主因是模型字符串无效,不是模型服务故障

现象:

  1. Telegram 消息可成功转发到 OpenCode。
  2. OpenCode 会话停在 Queue/不继续。

证据:

  1. 报错:ProviderModelNotFoundError
  2. 报错参数:providerID: "opencode", modelID: "minimax-m2.1-free"

结论:

  1. 会话阻塞由“配置的 provider/model 组合无效”触发。
  2. 这类错误在 UI 上可能表现为“队列卡住”,但本质是模型解析失败。

工程建议:

  1. 启动后第一步先执行 opencode models <provider> 校验模型名。
  2. 统一用完整 provider/model 字符串,避免历史别名遗留。

3.2 MiniMax 双线路是高频误配点

发现:

  1. OpenCode 同时存在两条 MiniMax Coding Plan provider:
    • minimax-cn-coding-planminimaxi.com
    • minimax-coding-planminimax.io
  2. 两者都使用 MINIMAX_API_KEY,但 key 与线路必须匹配。

结论:

  1. invalid api key 在该场景下常见根因是“线路选对了模型,但 key 来源/作用域不匹配”。

工程建议:

  1. 显式固定 provider(如国区使用 minimax-cn-coding-plan)。
  2. opencode auth list 同时检查 Credentials 与 Environment 生效来源。
  3. 排查 shell 环境中旧 MINIMAX_API_KEY 覆盖本地 auth 的情况。

3.3 多实例同端口会制造“启动成功但不可用”假象

现象:

  1. opencode --port 4096 打印插件初始化日志后似乎无响应。

根因:

  1. 旧进程已监听 127.0.0.1:4096,新进程无法正常接管。

工程建议:

  1. 启动前固定检查端口占用(lsof -iTCP:4096 -sTCP:LISTEN)。
  2. 管理脚本加入“单实例守护”或启动前清理策略。

3.4 fetch failed 在 OpenClaw 当前链路中是非致命异常

现象:

  1. 日志出现 Non-fatal unhandled rejection: TypeError: fetch failed

结论:

  1. 当前实现下该异常未直接中断主链路,但属于稳定性预警信号。

工程建议:

  1. 对外部 HTTP 调用补充超时与重试策略。
  2. 把该异常频率纳入监控,超过阈值触发告警。

3.5 Question Tool 自定义回答 Queue 的根因是“回复路径错误”

现象:

  1. 用户已点击 ✏️ 自定义回答,但后续文本输入后界面仍停在 QUEUED

根因:

  1. 文本发给了业务机器人(如 @Napsta...),被当作普通任务转发。
  2. 没有 reply Permission Bot 的自定义输入提示消息,Listener 无法做强绑定匹配。

修复:

  1. 点击 qcustom 后,Listener 发送 force_reply 提示。
  2. 用户 reply 该提示消息;Listener 通过 reply_to_message_id 精确识别回答并回传。

收益:

  1. 明显降低群聊并发下的误匹配概率。
  2. 与用户交互心智一致,排障成本更低。

4. Question Tool 官方 API 能力实测结论

4.1 可用端点(OpenCode v1.1.53)

  1. GET /question
  2. POST /question/{requestID}/reply
  3. POST /question/{requestID}/reject

4.2 数据结构关键点

  1. GET /question 返回包含:

    • id(requestID)
    • sessionID
    • tool.callID
    • questions[]
  2. reply payload 要求:

{
  "answers": [["A"]]
}

补充:

  1. answers 为二维字符串数组。
  2. ["A"]["问题文本","A"]均可被接受,但输出语义略有不同。

4.3 一个关键反模式

发现:

  1. 若在 tool.execute.before 中阻塞 question 执行(例如轮询等待用户输入),GET /question 会长期返回空列表。

结论:

  1. 这会“抑制官方 question 生命周期”,导致外部 API 无法拿到 requestID。

5. 已落地的工程实现(无 throw hack)

5.1 设计原则

  1. hermes-hook.js 只负责转发问题到 Telegram,不阻塞、不注入异常。
  2. permission-listener.js 负责回传答案到 /question/{requestID}/reply
  3. requestID 通过 callID + sessionID 匹配获取。

5.2 匹配与回传策略

  1. GET /question?directory=<project_dir>
  2. 优先 tool.callID 精确匹配。
  3. 回退到同 sessionID 的唯一 question。
  4. 成功后调用 reply,并清理 pending。
  5. 过期条目调用 reject 做关闭清理。

5.3 目录参数的重要性

发现:

  1. 不带 directory 时可能查不到当前会话的 question。

策略:

  1. 在 pending 中持久化 directory,所有 question API 调用统一携带。

6. 开源社区可复用的排障顺序

建议按以下顺序排查:

  1. 模型字符串是否有效:opencode models <provider>
  2. provider 与 key 是否同线路:opencode auth list
  3. 端口是否被旧实例占用:lsof -iTCP:<port> -sTCP:LISTEN
  4. Question API 是否可见:GET /question?directory=<cwd>
  5. Question 回传格式是否正确:{"answers":[["A"]]}
  6. 自定义回答是否 reply 了 Permission Bot 提示消息(而非 @Napsta...
  7. Listener 日志是否完整:callback_query(qcustom)收到 messagequestion 已回传

7. 对社区的贡献点

  1. 给出了 Question Tool 官方回传在 v1.1.53 的可运行证据链。
  2. 明确了 tool.execute.before 阻塞会抑制 /question 的机制性问题。
  3. 给出了可维护、低耦合的生产实现路径(分层职责 + requestID 匹配 + 过期 reject)。
  4. 给出了 MiniMax 双线路在真实项目中的配置边界与踩坑防护。
  5. 明确了 Telegram 群聊下自定义回答的稳定交互范式(force_reply + reply_to 绑定)。

8. 关联文档

  1. /Users/napstablook/.config/opencode/HERMES/docs/技术文档_QuestionTool官方API回传_2026-02-13.md
  2. /Users/napstablook/.config/opencode/HERMES/docs/问题排查_OpenCode队列阻塞与InvalidApiKey_2026-02-13.md
  3. /Users/napstablook/.config/opencode/HERMES/docs/question-tool-api-exploration_2026-02-11.md