跳转到主要内容
本页解释 middleware.js 的基础运行模型和通用返回体。开始写业务逻辑前,先确认你的插件运行在消息、HTTP 路由还是 cron / fake 上下文。

运行上下文

每次插件运行都会有一个 senderID。消息触发时,senderID 包含 IM、账号、会话和用户;cron 触发时使用 fake 运行上下文;路由触发时使用路由上下文。
场景getImtype()回复目标主动推送账号选择
消息触发当前消息 IM,例如 qqweixin当前会话和当前接收账号目标 IM 等于当前 IM 时,默认使用当前会话账号。
cron / fakefakereply* 默认不发送真实 IM 消息使用目标 IM 的默认账号。
HTTP 路由路由上下文reply(...) / replyMarkdown(...) 会写入路由响应数据使用目标 IM 的默认账号,除非显式传 account_id
跨 IM 推送当前上下文 IM 不等于目标 IM不适用使用目标 IM 的默认账号。
push(...) 可以通过 options.account_id 显式指定发送账号。显式 account_id 优先于当前会话账号和目标 IM 默认账号。多账号插件建议在文本主动推送时显式指定。
const { Sender, getSenderID, push } = require('./middleware.js')
const sender = new Sender(getSenderID())

// 消息来自 qq:bot_qq_2,且目标 IM 也是 qq:默认使用 bot_qq_2。
await push('qq', '123456', '', '通知', '处理完成')

// 显式 account_id 优先:这里会改用 bot_qq_ops。
await push('qq', '123456', '', '通知', '处理完成', {
  account_id: 'bot_qq_ops',
})

// 跨 IM 推送:消息来自 qq,但推到 weixin;默认使用 weixin 默认账号。
await push('weixin', '', 'wxid_user', '通知', '处理完成')

运行时返回包装

插件调用拿到的是 data 字段,不需要处理 HTTP 包装。底层运行时响应格式如下:
{
  "code": 0,
  "message": "成功",
  "data": {
    "ok": true
  },
  "request_id": "req_abc123"
}
如果请求失败,middleware.js 会把运行时错误转成 Error 抛出。

SendReceipt

文本、媒体、混合消息和撤回类方法通常返回发送回执。
{
  "ok": true,
  "message_id": "msg_123456",
  "messageid": "msg_123456",
  "message_ids": ["msg_123456"],
  "raw": {
    "adapter": "qq"
  },
  "action": "sendText"
}
ok
boolean
是否发送成功。适配器未显式返回时,运行时会补为 true
message_id
string
标准消息 ID。撤回消息时把它传给 recallMessage(...)
messageid
string
兼容旧插件的消息 ID 字段,通常与 message_id 相同。
message_ids
string[]
多段消息或适配器返回多个 ID 时使用。只有单条消息时通常包含一个 ID。
raw
unknown
适配器原始回执。需要排查平台问题时再读取。
error
string
适配器可能返回的失败说明。失败时优先检查 receipt.ok === falsereceipt.error

FileDownloadResult

fileDownload(...) 返回 FileDownloadResultdownloadAdapterFile(...) 返回同样字段并额外包含 okurlaction
{
  "ok": true,
  "action": "resolveFileURL",
  "url": "https://adapter.example/files/card_keys.csv",
  "path": "/opt/autclaw/file/imports/card_keys.csv",
  "file_path": "/opt/autclaw/file/imports/card_keys.csv",
  "file_name": "card_keys.csv",
  "mime_type": "text/csv",
  "file_size": 12345
}
ok
boolean
downloadAdapterFile(...) 一定返回。表示文件已保存。
action
string
当 SDK 需要先通过适配器把平台文件 ID 换成下载 URL 时,值通常是 resolveFileURL;直接下载 URL 时可能为空。
url
string
实际下载地址。可能是原始 URL,也可能是适配器解析后的临时 URL。
path
string
保存后的本地路径。推荐把这个字段传给 replyImage(...)replyFile(...) 等媒体方法。
file_path
string
path 相同,兼容更明确的字段名。
file_name
string
保存后的文件名。
mime_type
string
检测或传入的 MIME 类型,例如 image/pngtext/csv
file_size
number
文件大小,单位为字节。

MediaItem

sender.getMediaItems() 返回标准化媒体数组。它会优先返回最近一次 listen(...) / input(...) 捕获到的媒体;否则返回当前事件里的 media_items / mediaItems
[
  {
    "type": "file",
    "source": "file_123",
    "name": "card_keys.csv",
    "mime_type": "text/csv",
    "platform_payload": {
      "file_id": "file_123"
    }
  },
  {
    "type": "image",
    "source": "https://example.com/demo.png",
    "name": "demo.png",
    "mime_type": "image/png"
  }
]
type
'image' | 'voice' | 'video' | 'file' | string
必填
媒体类型。当前标准化流程主要保留有 typesource 的媒体项。
source
string
必填
媒体来源。可能是 URL、本地路径、临时资源 ID、平台文件 ID 或适配器原始文件标识。
name
string
文件名或展示名。运行时会从 namefilenamefile_name 中标准化为 name
mime_type
string
MIME 类型。运行时会从 mime_typemimeType 标准化。
platform_payload
object
平台原始文件信息,例如 file_idpathurl。下载用户上传文件时直接把整个 MediaItem 传给 downloadAdapterFile(...)
不要自己拼接平台文件下载地址。把 MediaItem 原样传给 downloadAdapterFile(...),让适配器处理平台差异和临时 URL。

下一步

读取和回复消息

查看 Sender 的消息上下文、回复和撤回方法。

主动推送账号规则

查看 push(...)account_id 优先级和跨 IM 行为。
Last modified on June 3, 2026