225 lines
6.3 KiB
JavaScript
225 lines
6.3 KiB
JavaScript
// 消息发送工具
|
||
// 文件位置: D:\openclaw-multi-agent\scripts\send-message.js
|
||
// 功能: 发送消息到消息路由系统
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { exec } = require('child_process');
|
||
const { promisify } = require('util');
|
||
|
||
const execAsync = promisify(exec);
|
||
|
||
class MessageSender {
|
||
constructor() {
|
||
this.basePath = 'D:\\openclaw-multi-agent';
|
||
this.notificationsPath = path.join(this.basePath, 'shared', 'notifications', 'incoming');
|
||
|
||
// 确保目录存在
|
||
if (!fs.existsSync(this.notificationsPath)) {
|
||
fs.mkdirSync(this.notificationsPath, { recursive: true });
|
||
}
|
||
}
|
||
|
||
// 生成消息ID
|
||
generateMessageId() {
|
||
const timestamp = Date.now();
|
||
const random = Math.floor(Math.random() * 1000);
|
||
return `msg-${timestamp}-${random}`;
|
||
}
|
||
|
||
// 直接发送消息到Agent(绕过路由系统)
|
||
async sendDirect(agent, message) {
|
||
try {
|
||
// 转义消息中的特殊字符
|
||
const escapedMessage = message.replace(/"/g, '\\"');
|
||
const command = `openclaw agent --agent ${agent} --message "${escapedMessage}"`;
|
||
|
||
console.log(`Sending direct to ${agent}: ${message}`);
|
||
|
||
const { stdout, stderr } = await execAsync(command, {
|
||
cwd: this.basePath,
|
||
timeout: 30000
|
||
});
|
||
|
||
if (stderr && !stderr.includes('feishu_doc')) {
|
||
console.warn(`Agent ${agent} stderr: ${stderr}`);
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
agent,
|
||
output: stdout
|
||
};
|
||
} catch (error) {
|
||
console.error(`Failed to send to agent ${agent}:`, error.message);
|
||
return {
|
||
success: false,
|
||
agent,
|
||
error: error.message
|
||
};
|
||
}
|
||
}
|
||
|
||
// 通过文件系统发送消息(使用路由系统)
|
||
async sendViaFileSystem(prefix, message) {
|
||
try {
|
||
const fullMessage = `[${prefix}] ${message}`;
|
||
const messageId = this.generateMessageId();
|
||
|
||
const messageFile = {
|
||
id: messageId,
|
||
timestamp: new Date().toISOString(),
|
||
prefix,
|
||
message,
|
||
fullMessage,
|
||
status: 'pending',
|
||
source: 'cli'
|
||
};
|
||
|
||
const filePath = path.join(this.notificationsPath, `${messageId}.json`);
|
||
|
||
await fs.promises.writeFile(
|
||
filePath,
|
||
JSON.stringify(messageFile, null, 2),
|
||
'utf8'
|
||
);
|
||
|
||
console.log(`Message saved to file system: ${filePath}`);
|
||
console.log(`Message: ${fullMessage}`);
|
||
|
||
return {
|
||
success: true,
|
||
messageId,
|
||
filePath,
|
||
message: fullMessage
|
||
};
|
||
} catch (error) {
|
||
console.error('Error sending via file system:', error);
|
||
return {
|
||
success: false,
|
||
error: error.message
|
||
};
|
||
}
|
||
}
|
||
|
||
// 批量发送消息
|
||
async sendBatch(messages) {
|
||
const results = [];
|
||
|
||
for (const msg of messages) {
|
||
const { prefix, message, method = 'direct' } = msg;
|
||
|
||
let result;
|
||
if (method === 'direct') {
|
||
// 需要将前缀映射到agent
|
||
const agentMap = {
|
||
'PM': 'pm',
|
||
'BE': 'backend',
|
||
'FE': 'frontend',
|
||
'QA': 'qa'
|
||
};
|
||
|
||
const agent = agentMap[prefix] || 'pm';
|
||
result = await this.sendDirect(agent, `[${prefix}] ${message}`);
|
||
} else {
|
||
result = await this.sendViaFileSystem(prefix, message);
|
||
}
|
||
|
||
results.push({
|
||
...msg,
|
||
result
|
||
});
|
||
|
||
// 延迟一下,避免太快
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
}
|
||
|
||
return results;
|
||
}
|
||
}
|
||
|
||
// 命令行接口
|
||
if (require.main === module) {
|
||
const sender = new MessageSender();
|
||
|
||
const command = process.argv[2];
|
||
|
||
async function main() {
|
||
switch (command) {
|
||
case 'direct':
|
||
const agent = process.argv[3];
|
||
const message = process.argv.slice(4).join(' ');
|
||
|
||
if (!agent || !message) {
|
||
console.error('Usage: node send-message.js direct <agent> <message>');
|
||
console.error('Example: node send-message.js direct pm "[PM] 查看任务"');
|
||
process.exit(1);
|
||
}
|
||
|
||
const result = await sender.sendDirect(agent, message);
|
||
console.log(JSON.stringify(result, null, 2));
|
||
break;
|
||
|
||
case 'file':
|
||
const prefix = process.argv[3];
|
||
const msg = process.argv.slice(4).join(' ');
|
||
|
||
if (!prefix || !msg) {
|
||
console.error('Usage: node send-message.js file <prefix> <message>');
|
||
console.error('Example: node send-message.js file PM "查看任务"');
|
||
process.exit(1);
|
||
}
|
||
|
||
const fileResult = await sender.sendViaFileSystem(prefix, msg);
|
||
console.log(JSON.stringify(fileResult, null, 2));
|
||
break;
|
||
|
||
case 'test':
|
||
// 测试消息
|
||
const testMessages = [
|
||
{ prefix: 'PM', message: '查看当前任务状态', method: 'direct' },
|
||
{ prefix: 'BE', message: '查看分配的任务', method: 'direct' },
|
||
{ prefix: 'FE', message: '查看设计稿', method: 'direct' },
|
||
{ prefix: 'QA', message: '查看测试报告', method: 'direct' }
|
||
];
|
||
|
||
console.log('Sending test messages...');
|
||
const batchResults = await sender.sendBatch(testMessages);
|
||
|
||
console.log('\n=== Test Results ===');
|
||
batchResults.forEach((item, index) => {
|
||
console.log(`\n${index + 1}. [${item.prefix}] ${item.message}`);
|
||
console.log(` Success: ${item.result.success}`);
|
||
if (item.result.error) {
|
||
console.log(` Error: ${item.result.error}`);
|
||
}
|
||
});
|
||
break;
|
||
|
||
case 'help':
|
||
default:
|
||
console.log(`
|
||
Message Sender Tool - Usage:
|
||
node send-message.js direct <agent> <message> # 直接发送到Agent
|
||
node send-message.js file <prefix> <message> # 通过文件系统发送
|
||
node send-message.js test # 发送测试消息
|
||
node send-message.js help # 显示帮助
|
||
|
||
Examples:
|
||
node send-message.js direct pm "[PM] 查看任务"
|
||
node send-message.js file PM "查看任务"
|
||
node send-message.js test
|
||
|
||
Available agents: pm, backend, frontend, qa
|
||
`);
|
||
break;
|
||
}
|
||
}
|
||
|
||
main().catch(error => {
|
||
console.error('Fatal error:', error);
|
||
process.exit(1);
|
||
});
|
||
}
|
||
|
||
module.exports = MessageSender; |