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

93
electron/main-chat-fix.js Normal file
View File

@@ -0,0 +1,93 @@
// 修复:使用正确的 Gateway API 发送消息
// 转发消息到 OpenClaw - 使用 chat.send 方法
async forwardMessageToOpenClaw(frame) {
if (!openclawConnection || !openclawConnection.isConnected) {
console.log('[WeCom] OpenClaw not connected, skipping forward');
return;
}
const body = frame.body;
const chatId = body.chatid || body.from.userid;
const chatType = body.chattype === 'group' ? 'group' : 'direct';
const messageId = body.msgid;
const reqId = frame.headers.req_id;
reqIdMap.set(chatId, reqId);
// 提取文本
let text = '';
if (body.text?.content) {
text = body.text.content;
} else if (body.mixed?.msg_item) {
for (const item of body.mixed.msg_item) {
if (item.msgtype === 'text' && item.text?.content) {
text += item.text.content + '\n';
}
}
} else if (body.voice?.content) {
text = body.voice.content;
}
if (body.chattype === 'group') {
text = text.replace(/@\S+/g, '').trim();
}
// 构建 sessionKey格式wecom:chatType:chatId
const sessionKey = `wecom:${chatType}:${chatId}`;
// 处理媒体文件
const attachments = [];
// 下载图片
if (body.image?.url) {
try {
console.log('[WeCom] Downloading image:', body.image.url);
const { buffer, filename } = await downloadFile(body.image.url, body.image.aeskey);
const saved = await saveMediaFile(buffer, filename, 'inbound');
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);
}
}
// 下载文件
if (body.file?.url) {
try {
console.log('[WeCom] Downloading file:', body.file.url);
const { buffer, filename } = await downloadFile(body.file.url, body.file.aeskey);
const saved = await saveMediaFile(buffer, filename, 'inbound');
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);
}
}
// 使用 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 作为幂等键
}
};
console.log('[OpenClaw] Sending via chat.send:', sessionKey);
openclawConnection.send(JSON.stringify(chatSendMessage));
console.log(`[Forward] WeCom -> OpenClaw: ${messageId}`);
}