npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sunflowermm/openclaw-xrk-bridger

v0.2.13

Published

OpenClaw 通道插件:通过 XRK-AGT 自定义 Tasker 转发 QQ 事件。

Readme

🌉 OpenClaw-xrk-bridger

OpenClaw Gateway 通道插件:以 WebSocket 客户端接入 XRK-AGT 的 XrkBridge Tasker,将 XRK 的主人私聊等事件接入 OpenClaw Agent,并将回复回推到 XRK-AGT,由 XRK-AGT 再发回 QQ / 其他端。

XRK-AGT Openclaw-Core License: MIT


📦 项目定位

  • 通道类型:OpenClaw Gateway 通道 / 插件,通道 ID 示例:xrk-agt-bridge
  • 主要职责
    • 作为 WebSocket 客户端 连接 XRK-AGT 的 /XrkBridge
    • 接收 XRK 标准化后的入站消息 → 交给 OpenClaw Agent / Workflow 处理
    • 将 Agent 回复(文本 + 文件)通过同一 WS 回传 XRK-AGT
  • XRK-AGT 侧对应模块Openclaw-Core(或 XRK-AGT 仓库内的 core/Openclaw-Core/

🔧 运行依赖

  • Node.js ≥ 18(建议 24+)
  • OpenClaw Gateway(兼容 2026.x)
  • 已安装并启用 XRK-AGT,且 Openclaw-Core 总开关 data/openclaw/openclaw.yamlenabled: true

🚀 安装到 OpenClaw

方式一:通过 OpenClaw CLI 安装(推荐)

在任意终端执行(需 OpenClaw CLI 已安装且已配置 npm registry):

openclaw plugins install @sunflowermm/openclaw-xrk-bridger

安装完成后,OpenClaw 会在:

  • Windows:%USERPROFILE%\.openclaw\extensions\openclaw-xrk-bridger\
  • Linux/macOS:~/.openclaw/extensions/openclaw-xrk-bridger/

下创建插件目录,并在配置中注册一个可在控制台中编辑的通道。

方式二:从源码构建后手动部署(开发者)

  1. 本地构建生成 dist/

    pnpm install
    pnpm build
  2. 将以下文件复制到 OpenClaw 的扩展目录,例如:

    • dist/*.js
    • openclaw.plugin.json
    • package.json

    目标目录示例(Windows):

    • %USERPROFILE%\.openclaw\extensions\openclaw-xrk-bridger\
  3. 之后同样通过 Gateway 控制台进行配置(见下文),无需手动编辑 openclaw.json


⚙️ 在 Gateway 控制台中配置

安装完成并启动 Gateway 后,打开 OpenClaw Gateway 控制台

  1. 进入「通道 / Channels」或「插件 / Plugins」页面,找到 XRK-AGT Bridge(id: openclaw-xrk-bridger 或类似)。
  2. 点击进入配置表单,你会看到以下字段(由 openclaw.plugin.jsonconfigSchemauiHints 自动生成):
    • XRK-AGT Bridge WS 地址 (wsUrl):XRK-AGT 的 XrkBridge WebSocket 地址,格式 ws://<host>:<port>/XrkBridge,端口与 XRK-AGT 的 HTTP/WS 端口一致(如 11451),示例:ws://127.0.0.1:11451/XrkBridge
    • XRK-AGT 鉴权 Token (accessToken)(可选,敏感字段):若 XRK-AGT 侧对 WS 做鉴权,可在此填写,插件会以 Authorization: Bearer <accessToken> 请求头连接。
  3. 填写完成后点击保存,OpenClaw 会自动将配置写入:
  • Windows:%USERPROFILE%\.openclaw\openclaw.json
  • Linux/macOS:~/.openclaw/openclaw.json

无需手工修改 JSON。


🔄 协议概要(XRK ↔ OpenClaw)

  • XRK → OpenClaw(入站)
    XRK 侧 Tasker 需将任意“主人私聊”等事件归一为:

    { "id": "...", "type": "message", "kind": "direct" | "group", "selfId": "...", "userId": "...", "groupId": "...", "text": "..." }

    (如需扩展图片/文件,可在此对象上增加 files 字段并在 XRK 自行消费。)

  • OpenClaw → XRK(回复)
    本通道会将 Agent 回复转换为:

    {
      "id": "...",
      "type": "reply",
      "to": { "kind": "direct" | "group", "userId": "...", "groupId": "..." },
      "text": "...",
      "files": [{ "url": "...", "name": "..." }]
    }

    id 与入站一致,用于请求-响应匹配,files 中的资源由 XRK 再发到 QQ / 其它前端。


底层谁在发文件(.openclaw 内)

本插件内实际把文件发到 XRK 的只有两处,都在 src/channel.ts

| 路径 | 触发方 | 说明 | |------|--------|------| | deliver(payload) | OpenClaw 运行时 dispatchReplyFromConfig 在 Agent 回复就绪后回调 | 收到 payload.files / payload.mediaUrls,转成 client.sendReply({ text, mediaUrls, files }) 发往 XRK。若 runtime 只传 mediaUrls 不传 files,则无文件名。 | | outbound.sendMedia({ to, text, mediaUrl, accountId, name? }) | 核心的 message 工具(Agent 调「发文件」时) | 原先只发 mediaUrls,无 name,导致 QQ 显示 file.pptx已改:从 mediaUrl 路径推断文件名(或使用传入的 name),非图片一律用 files: [{ url, name }] 发往 XRK,QQ 即可显示正确文件名。 |

结论:负责发送文件的是上述两处;其中「Agent 用 message 工具发文件」走 sendMedia。当前核心只传 mediaUrl 不传 name,QQ 上正确显示的文件名来自本插件的路径推断;若核心后续传入 name,会优先使用。


排查:回复带文件但 QQ 显示 file.xxx / 后端收到「两文件 + 三次文字」

现象:OpenClaw 终端里 [XRK-Bridge] deliver 收到 payload 一直显示 mediaUrls=0 files=0,但 XRK 端实际收到了带文件的回复,且 QQ 上文件名为 file.pptx

原因:带附件的回复走的是 outbound.sendMedia(message 工具),未走 deliver。旧版 sendMedia 只发 mediaUrls,不带 name

已做修改sendMedia 现会从 mediaUrl(如本地路径、file://)推断文件名,并支持可选参数 name;非图片一律以 files: [{ url, name }] 发往 XRK,QQ 会显示正确名称。若核心的 message 工具把 name 一并传给 sendMedia,会优先使用该 name

调试日志说明(全在 [XRK-Bridge] 前缀下):

  • deliver 路径(Agent 回复走统一派发时):会看到 deliver 收到 payload: keys=[...] text=有/无 mediaUrls=N files=M,接着 sendReply 将发往 XRK,最后 client.sendReply 发出 → XRK。若这里始终是 mediaUrls=0 files=0,说明带文件的回复没有走 deliver
  • sendMedia 路径(Agent 用 message 工具发文件时):应看到 outbound.sendMedia 被调用 to=... mediaUrl=... name=...,接着 sendMedia 转换: ... inferredName=... → files(带name),再 sendMedia 将发往 XRK: ... files=1 names=[...],最后 client.sendReply 发出 → XRK: ... files=1 fileNames=[...]
  • 若发文件时从没出现过 outbound.sendMedia 被调用:说明核心没有通过本插件的 sendMedia 发文件,而是用别的路径(例如直接写 WebSocket、或走其他 channel 接口)。需要在 OpenClaw 主仓里搜「发文件 / 发 reply / message 工具实现」,确认是否调用了当前 channel 的 outbound.sendMedia 并传入 mediaUrl(及尽量带 name)。
  • 若 AI 说传了 name 但日志显示 name=(未传):看同一条日志里的 收到参数 keys=[...],核心可能用了别的字段名。本插件已从下列任一字段取显示名(优先第一个有值):namefileNamefilenamedisplayNamefile_namefile.name。若 keys 里有你期望的档名但字段名不在上述列表,可在 bridger 的 sendMedia 里为该字段加一次读取。

🔗 相关项目


📄 许可证

本项目基于 MIT License 开源,详见 LICENSE