Skip to main content

Baidu Infoflow (如流) channel plugin for Hermes Agent

Project description

hermes-infoflow

Baidu Infoflow(如流)Channel 插件 for Hermes Agent

把企业内的 Infoflow 群聊 / 私聊接入 Hermes,机器人可以接收并回复 Markdown / 链接 / 图片消息,支持 @-mention 触发、消息撤回(recall)、cron 定时投递等。本仓库对齐 openclaw-infoflow 的发布形态:一个主插件包(hermes-infoflow) + 一个独立的安装 CLI(hermes-infoflow-tools)+ 与 OpenClaw 同款的 scripts/deploy.sh 脚本。

Hermes 主仓零改动:完全靠 hermes-agent 已存在的 4 条插件加载路径接入。


功能(balanced scope · v0.2)

  • ✅ Webhook 接入 + AES-ECB 解密 + echostr 签名校验
  • ✅ 群聊 / 私聊 文本 & Markdown 双向(含分块)
  • ✅ 图片入站(含 Bearer- 鉴权 fallback 下载)+ 出站(含 path-traversal 校验)
  • ✅ @-mention 检测:require_mention + 五种 reply_modeignore / record / mention-only / mention-and-watch / proactive)+ watch_mentions + watch_regex
  • ✅ 群聊 follow-up 窗口(INFOFLOW_FOLLOW_UP)与 per-group 配置覆盖(INFOFLOW_GROUPS
  • ✅ 自有消息回环防护(robotId 自动发现后丢弃 bot 自身转发)
  • ✅ 消息撤回(recall):私聊 + 群聊;agent tool infoflow_recall_message;SQLite 持久化 sent-message store(cron 子进程可 count 撤回)
  • ✅ 长整型 message_id 精度保护(19 位数字不丢精度)
  • ✅ cron deliver=infoflow 投递(home channel)+ 独立进程发送(standalone_sender_fn
  • ⚠️ 已知限制(计划在后续版本支持):
    • 单账号(不支持 OpenClaw 的 accounts.* 子配置)
    • WebSocket 接入模式未实现(仅 webhook)

4 种安装方式

主推 directory-style 三种(A / B --mode extract / D);entry-point 方式(B --mode pip / C)作为高级用法。

A. hermes plugins install(最像 OpenClaw 体验)

hermes plugins install <github-owner>/hermes-infoflow
hermes plugins enable infoflow
hermes gateway restart

hermes 内置命令;git clone --depth 1~/.hermes/plugins/infoflow/

B. hermes-infoflow-tools(对齐 npx ... update

推荐用 pipx runuvx,免去全局污染。

正式版(stable):

pipx run hermes-infoflow-tools update --version 0.2.0

Beta 版(PEP 440 prerelease;不会被默认 pip install 拉到):

pipx run hermes-infoflow-tools update --version 0.2.0b1

子命令参数:

  • --version <ver>:PyPI 版本号(缺省 latest,会被解析为当前正式版)
  • --index-url <url>:PyPI 源(默认 https://pypi.org/simple
  • --mode extract(默认):pip download sdist → 解包 → rsync 到 ~/.hermes/plugins/infoflow/;体验对齐 OpenClaw。
  • --mode pippip install --upgrade hermes-infoflow==<ver> 到 site-packages。注意:此模式 hermes 不读 plugin.yamlhermes config 不会列 INFOFLOW_*
  • --channel-id <id>:目标目录名(默认 infoflow,仅在你知道自己在做什么时改)
  • --dry-run:仅打印命令

C. pip install hermes-infoflow(最 Pythonic)

pip install hermes-infoflow
hermes plugins enable infoflow
hermes gateway restart

通过 PyPI 包的 hermes_agent.plugins entry-point 让 hermes 自动发现。限制:hermes 在 entry-point 模式下不读 plugin.yaml,所以 hermes config 不会列 INFOFLOW_* —— 需要你手动 exporthermes config set 这些环境变量。

D. 本地开发:bash scripts/deploy.sh

git clone https://github.com/chbo297/hermes-infoflow
cd hermes-infoflow
bash scripts/deploy.sh             # 同步到 ~/.hermes/plugins/infoflow/、重启 gateway
bash scripts/deploy.sh --dry-run   # 仅打印操作

deploy.sh 会同步插件并自动选择 Python:优先 hermes / pipxhermes-agent venv,再尝试 python3。若缺少 cryptography / aiohttp / pyyaml,默认会尝试 pipx inject hermes-agent … 或对当前解释器 pip install(可用 HERMES_DEPLOY_AUTO_PIP=0 关闭)。若检测到的解释器与 gateway 实际用的 pipx venv 不一致,脚本会打印 warning。

镜像 openclaw-infoflow/scripts/deploy.sh


配置(环境变量)

任一安装路径完成后,下面这些环境变量都需要在 hermes 运行的 shell / ~/.hermes/.env 里设置。

必需

变量 含义
INFOFLOW_API_HOST 如流 API 根地址,例如 https://api.infoflow.example.com
INFOFLOW_APP_KEY 应用 appKey
INFOFLOW_APP_SECRET 应用 appSecret(原始;插件会自动 MD5 lowercase hex)
INFOFLOW_CHECK_TOKEN echostr 签名校验用 token
INFOFLOW_ENCODING_AES_KEY base64-URL-safe 的 AES 密钥(16/24/32 字节明文,对应 AES-128/192/256)

可选

变量 默认 含义
INFOFLOW_APP_AGENT_ID 私聊撤回必须;如流后台「应用 ID」
INFOFLOW_ROBOT_NAME 机器人显示名,用于 @-mention 识别
INFOFLOW_PORT 8646 Webhook 监听端口
INFOFLOW_HOST 0.0.0.0 Webhook 监听地址
INFOFLOW_WEBHOOK_PATH /webhook/infoflow Webhook 路径
INFOFLOW_HOME_CHANNEL cron deliver=infoflow 缺省目标,如 bobgroup:12345
INFOFLOW_HOME_CHANNEL_NAME 同上 Home channel 显示名
INFOFLOW_REPLY_MODE mention-and-watch ignore / record / mention-only / mention-and-watch / proactive
INFOFLOW_REQUIRE_MENTION true 群消息是否仅在 @ 时响应
INFOFLOW_WATCH_MENTIONS 逗号分隔;命中后即使没 @ 机器人也会触发
INFOFLOW_WATCH_REGEX 正则匹配触发(多行或 `
INFOFLOW_FOLLOW_UP true 机器人回复后群聊 follow-up 窗口是否开启
INFOFLOW_FOLLOW_UP_WINDOW 300 follow-up 窗口秒数
INFOFLOW_GROUPS 按群 ID 的 JSON 配置覆盖
INFOFLOW_ADMIN_USER 管理员 uuapName(敏感工具权限)
INFOFLOW_ALLOWED_USERS 逗号分隔的 uuapName allowlist
INFOFLOW_ALLOW_ALL_USERS false 允许所有人(仅开发)
HERMES_STATE_DIR ~/.hermes/state sent-messages.db 等状态目录

设置完后:

hermes config show                  # 验证当前生效配置
hermes gateway restart              # 重新加载插件
hermes gateway status               # 期望看到 "infoflow: running"

Infoflow 后台 webhook 设置

进入如流企业后台的应用页面,把回调地址填成:

https://<your-domain>/webhook/infoflow

注意:必须配 HTTPS。如果你的服务器对公网仅暴露 8646 / 内网端口,请在前面挂反向代理 + TLS。

Caddy 示例

hermes.example.com {
    reverse_proxy /webhook/infoflow localhost:8646
}

Nginx 示例

server {
    listen 443 ssl http2;
    server_name hermes.example.com;
    ssl_certificate     /etc/letsencrypt/live/hermes.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hermes.example.com/privkey.pem;

    location /webhook/infoflow {
        proxy_pass http://127.0.0.1:8646/webhook/infoflow;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
}

Cloudflare Tunnel 示例

# ~/.cloudflared/config.yml
tunnel: <tunnel-id>
credentials-file: /Users/bo/.cloudflared/<tunnel-id>.json
ingress:
  - hostname: hermes.example.com
    service: http://localhost:8646
  - service: http_status:404

撤回(recall)

机器人可调用 infoflow_recall_message agent tool 撤回自己刚发的消息。两种用法:

// 按具体 message_id(任意源)
{ "target": "group:12345", "message_id": "1859713223686736431" }

// 不传 message_id,自动撤回最近 N 条
{ "target": "alice", "count": 1 }

⚠️ 跨进程撤回:自 v0.2.0 起,出站消息默认写入 ~/.hermes/state/infoflow/sent-messages.db(可用 HERMES_STATE_DIR 覆盖),cron 子进程与 gateway 共享 count 撤回。若 SQLite 不可用则回退为 gateway 进程内内存 ring buffer。

⚠️ 切勿把 用户发来的入站 message_id 当成撤回目标 —— 那是用户的消息,不是机器人的,API 会返回失败。机器人发出的消息 id 在 LLM 的工具结果里能拿到;或者用 count=1 撤回最近一条。


安全注意事项

  • AES-ECB:Infoflow 服务端的设计选择(与 wecom 的 CBC 不同)。ECB 在通常情况下是不安全的密码模式;本插件做了我们能做的(PKCS7、严格 key length、签名校验)。详见 hermes_infoflow/crypto.py
  • Webhook 公网暴露:必须配 TLS + 反向代理;端口上的明文请求只能被 echostr 签名 + AES 密文形式保护,不要 0.0.0.0 直接暴露。
  • 本地图片 path traversal:插件只接受 ~/.hermes/media//tmp、系统临时目录里的 file:// 路径。其余路径会被拒绝。
  • 大整数 message_id:内部统一存字符串;撤回 API 调用时手工拼 JSON 字面量,避免被 json.dumps 误加引号。

发版流程

PyPI 没有 npm 的 dist-tag 概念。我们用 PEP 440 prerelease 后缀来表达 beta。两条 stream 各自的完整流程:

A. 正式版(stable)发布流程

将下方所有 <X.Y.Z> 替换为目标正式版本号(不带 b/a/rc 后缀):

# 1) 改主包 pyproject.toml 的 version 字段
hatch version <X.Y.Z>
# 同步 tools 子包版本(与主包对齐)
hatch version <X.Y.Z> --pyproject tools/hermes-infoflow-tools/pyproject.toml

# 2) 同步 README 安装命令版本号
python scripts/sync_readme_install_version.py

# 3) 编辑 CHANGELOG.md 顶部,添加本版本章节

# 4) 发布前校验
ruff check hermes_infoflow tools tests
pytest -q

# 5) 提交、打 tag、push
git add pyproject.toml tools/hermes-infoflow-tools/pyproject.toml README.md CHANGELOG.md
git commit -m "<X.Y.Z>"
git tag <X.Y.Z>
git push origin main <X.Y.Z>

# 6) CI 自动构建并发布到 PyPI(主包 + tools 子包)
#    见 .github/workflows/publish.yml

B. Beta 预发布流程

将下方所有 <X.Y.Z-beta.N> 替换为目标预发版本号,写成 PEP 440 形式<X.Y.Z>b<N>(例如 0.1.0b1不要0.1.0-beta.1,PyPI 不接受):

hatch version <X.Y.ZbN>
hatch version <X.Y.ZbN> --pyproject tools/hermes-infoflow-tools/pyproject.toml
python scripts/sync_readme_install_version.py
# ...同上 commit/tag/push...

PyPI 默认 把 prerelease 当成 pip install <pkg> 的目标,所以发完 beta 后用户安装 stable 不受影响。要装 beta:

pip install --pre hermes-infoflow                # 拉最新 prerelease
pip install hermes-infoflow==<X.Y.ZbN>           # 显式锁定

当前版本

hatch version 0.2.0
git tag 0.2.0
git push origin 0.2.0

排查:PyPI 上拉不到刚发的版本

# 1) 检查 PyPI 元数据已对外可见
pip index versions hermes-infoflow --pre
curl -s https://pypi.org/pypi/hermes-infoflow/json | python -m json.tool | head -40

# 2) 强制忽略本地缓存重拉
pip install --no-cache-dir --force-reinstall --upgrade hermes-infoflow==<version>

# 3) 看 GH Actions publish job 是否真的成功了
gh run list --workflow publish.yml --limit 3

开发

git clone https://github.com/chbo297/hermes-infoflow
cd hermes-infoflow

# 安装开发依赖
pip install -e ".[dev]"

# 运行单元测试(无需 hermes-agent)
pytest -q

# 运行所有测试(包括 adapter / registration,需要 hermes-agent 在 PYTHONPATH)
PYTHONPATH=/path/to/hermes-agent pytest -q

Linting / typecheck:

ruff check hermes_infoflow tools tests

部署到本地 hermes 一键测试:

bash scripts/deploy.sh

与 OpenClaw 仓库的对照

OpenClaw hermes-infoflow
npm 主包 @chbo297/infoflow PyPI 主包 hermes-infoflow
npm tools @chbo297/infoflow-openclaw-tools PyPI tools hermes-infoflow-tools
~/.openclaw/extensions/infoflow/ ~/.hermes/plugins/infoflow/
openclaw.jsonplugins.entries.<id>.enabled (dict) ~/.hermes/config.yamlplugins.enabled: [...] (list)
openclaw plugins install @chbo297/infoflow@X hermes plugins install <repo>hermes-infoflow-tools update --version X
npx -y @chbo297/infoflow-openclaw-tools update pipx run hermes-infoflow-tools update
--tag beta(npm dist-tag) PEP 440 prerelease 0.1.0b1 + pip install --pre

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hermes_infoflow-0.2.0.tar.gz (106.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hermes_infoflow-0.2.0-py3-none-any.whl (101.0 kB view details)

Uploaded Python 3

File details

Details for the file hermes_infoflow-0.2.0.tar.gz.

File metadata

  • Download URL: hermes_infoflow-0.2.0.tar.gz
  • Upload date:
  • Size: 106.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hermes_infoflow-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5e3555cbaaa72c37be026f55659cda6a00f454ddf1d9cb352223c08ea5dc2bf5
MD5 9cfdc05809a395673363f716d8287aaf
BLAKE2b-256 f6fe166c6b9755a3b09c0ea4bff5ca220c272df764950ca2e02bea7ba8a4c98a

See more details on using hashes here.

Provenance

The following attestation bundles were made for hermes_infoflow-0.2.0.tar.gz:

Publisher: publish.yml on chbo297/hermes-infoflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hermes_infoflow-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: hermes_infoflow-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 101.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for hermes_infoflow-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e03898516a0c1a203143e543a54bd1721768067aaef1d9dbd5ecfe7b6723389a
MD5 921e819f430c5f1a01a5e248dd6daeb3
BLAKE2b-256 1dcef8eab8c568db991a559a3e929647ce54aa427666b1e097a0cff2d1440b55

See more details on using hashes here.

Provenance

The following attestation bundles were made for hermes_infoflow-0.2.0-py3-none-any.whl:

Publisher: publish.yml on chbo297/hermes-infoflow

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page