chore(scripts): add development, DSH and sidecar launchers
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Wechaty -> 私域 Agent API 适配器(示例)
|
||||
*
|
||||
* 安装:npm i wechaty wechaty-puppet-wechat4u
|
||||
* 启动:YAWAN_API_URL=https://agent.example.com \
|
||||
* YAWAN_WECHAT_BOT_SECRET=... YAWAN_WECHAT_AGENT_ID=3 node scripts/wechat_bot_adapter.mjs
|
||||
*
|
||||
* 个人微信协议有封号风险。生产环境建议把本适配层替换为腾讯官方
|
||||
* openclaw-weixin/iLink Bot,只保留下面 callAgent() 的 HTTP 调用。
|
||||
*/
|
||||
import crypto from 'node:crypto'
|
||||
import { WechatyBuilder, Message } from 'wechaty'
|
||||
|
||||
const apiUrl = (process.env.YAWAN_API_URL || 'http://127.0.0.1:8010').replace(/\/$/, '')
|
||||
const secret = process.env.YAWAN_WECHAT_BOT_SECRET || ''
|
||||
const agentId = Number(process.env.YAWAN_WECHAT_AGENT_ID || 0)
|
||||
if (!secret || !agentId) throw new Error('请设置 YAWAN_WECHAT_BOT_SECRET 和 YAWAN_WECHAT_AGENT_ID')
|
||||
|
||||
async function callAgent (conversationId, messageId, text) {
|
||||
const timestamp = String(Math.floor(Date.now() / 1000))
|
||||
const payload = `${timestamp}.${conversationId}.${messageId}.${text}`
|
||||
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex')
|
||||
const response = await fetch(`${apiUrl}/api/wechat/bot/reply`, {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json',
|
||||
'x-wechat-bot-timestamp': timestamp, 'x-wechat-bot-signature': signature },
|
||||
body: JSON.stringify({ agent_id: agentId, conversation_id: conversationId,
|
||||
message_id: messageId, text })
|
||||
})
|
||||
const data = await response.json().catch(() => ({}))
|
||||
if (!response.ok) throw new Error(data.detail || `API ${response.status}`)
|
||||
return data.reply || ''
|
||||
}
|
||||
|
||||
const bot = WechatyBuilder.build({
|
||||
name: process.env.YAWAN_WECHAT_SESSION || 'yawan-agent',
|
||||
puppet: 'wechaty-puppet-wechat4u',
|
||||
puppetOptions: { uos: true }
|
||||
})
|
||||
bot.on('scan', (qrcode, status) => console.log('请扫码登录微信:', status, qrcode))
|
||||
bot.on('login', user => console.log('微信 Bot 已登录:', user.name()))
|
||||
bot.on('logout', user => console.log('微信 Bot 已退出:', user.name()))
|
||||
bot.on('message', async message => {
|
||||
if (message.self() || message.type() !== Message.Type.Text) return
|
||||
const text = message.text().trim()
|
||||
if (!text) return
|
||||
const room = await Promise.resolve(message.room())
|
||||
const from = await Promise.resolve(message.from())
|
||||
const conversationId = room?.id || from?.id || 'unknown'
|
||||
const messageId = typeof message.id === 'function' ? message.id() : (message.id || crypto.randomUUID())
|
||||
try {
|
||||
const reply = await callAgent(conversationId, messageId, text)
|
||||
if (reply) await message.say(reply)
|
||||
} catch (error) {
|
||||
console.error('Agent 对话失败:', error.message)
|
||||
await message.say('系统暂时繁忙,请稍后再试。')
|
||||
}
|
||||
})
|
||||
await bot.start()
|
||||
Reference in New Issue
Block a user