feat: 使用正确的 Gateway API - chat.send

关键修复:
- 之前错误:直接发送 message.inbound 事件
- 现在正确:使用 Gateway 的 chat.send 方法

Gateway API 调用:
{
  "type": "req",
  "method": "chat.send",
  "params": {
    "sessionKey": "wecom:group:chatId",
    "message": "文本内容",
    "attachments": [{"type": "image", "path": "..."}],
    "deliver": true,
    "idempotencyKey": "messageId"
  }
}

会话管理:
- sessionKey 格式:wecom:chatType:chatId
- 例如:wecom:group:123456789 或 wecom:direct:zhangsan
- OpenClaw 会自动创建或复用会话

媒体文件处理:
- 下载企业微信图片/文件
- 保存到本地媒体目录
- 通过 attachments 参数传递给 chat.send

这样才符合 OpenClaw Gateway 协议规范!
This commit is contained in:
2026-03-10 03:39:28 +08:00
parent 15439de6d2
commit 0324938b81
4 changed files with 1503 additions and 24 deletions

View File

@@ -131,6 +131,7 @@ class WeComConnection {
}
}
// 转发消息到 OpenClaw - 使用 chat.send API
async forwardMessageToOpenClaw(frame) {
if (!openclawConnection || !openclawConnection.isConnected) {
console.log('[WeCom] OpenClaw not connected, skipping forward');
@@ -163,8 +164,11 @@ class WeComConnection {
text = text.replace(/@\S+/g, '').trim();
}
// 构建 sessionKey格式wecom:chatType:chatId
const sessionKey = `wecom:${chatType}:${chatId}`;
// 处理媒体文件
const mediaList = [];
const attachments = [];
// 下载图片
if (body.image?.url) {
@@ -172,7 +176,11 @@ class WeComConnection {
console.log('[WeCom] Downloading image:', body.image.url);
const { buffer } = await downloadFile(body.image.url, body.image.aeskey);
const saved = await saveMediaFile(buffer, 'image', 'inbound');
mediaList.push({ type: 'image', path: saved.path });
attachments.push({
type: 'image',
path: saved.path,
contentType: saved.contentType
});
console.log('[WeCom] Image saved:', saved.path);
} catch (error) {
console.error('[WeCom] Failed to download image:', error.message);
@@ -185,35 +193,33 @@ class WeComConnection {
console.log('[WeCom] Downloading file:', body.file.url);
const { buffer } = await downloadFile(body.file.url, body.file.aeskey);
const saved = await saveMediaFile(buffer, 'file', 'inbound');
mediaList.push({ type: 'file', path: saved.path });
attachments.push({
type: 'file',
path: saved.path,
contentType: saved.contentType
});
console.log('[WeCom] File saved:', saved.path);
} catch (error) {
console.error('[WeCom] Failed to download file:', error.message);
}
}
// 构建转发消息
const openclawMessage = {
type: 'event',
event: 'message.inbound',
payload: {
channel: 'wecom',
accountId: this.accountId,
message: {
id: messageId,
from: body.from.userid,
chatId: chatId,
chatType: chatType,
text: text,
media: mediaList,
timestamp: body.create_time || Date.now()
},
reqId: reqId,
botId: this.botId
// 使用 chat.send 方法发送消息到 OpenClaw
const chatSendMessage = {
type: 'req',
id: this.nextId(),
method: 'chat.send',
params: {
sessionKey: sessionKey,
message: text,
attachments: attachments.length > 0 ? attachments : undefined,
deliver: true, // 立即投递到 AI
idempotencyKey: messageId // 使用消息 ID 作为幂等键
}
};
openclawConnection.send(JSON.stringify(openclawMessage));
console.log('[OpenClaw] Sending via chat.send:', sessionKey);
openclawConnection.send(JSON.stringify(chatSendMessage));
console.log(`[Forward] WeCom -> OpenClaw: ${messageId}`);
}
@@ -420,7 +426,7 @@ class OpenClawConnection {
}
};
console.log('[OpenClaw] 发送 connect 请求:', JSON.stringify(connectMessage, null, 2));
console.log('[OpenClaw] 发送 connect 请求');
this.send(connectMessage);
}
@@ -625,7 +631,8 @@ function setupIpcHandlers() {
params: {
text: text,
sessionKey: `test_${Date.now()}`,
echo: true
deliver: true,
idempotencyKey: uuidv4()
}
};
console.log('[OpenClaw] Sending test message:', testMessage);