rpc-call.js 2.83 KB
/**
 * RPC Call Utility
 * 
 * 用于在 Hook 脚本中向 AgentBridge 发送控制指令。
 * Usage: node scripts/rpc-call.js --agent AgentName --command git/checkout --args feat/task-123
 */

const { WebSocket } = require('ws');
const path = require('path');
const fs = require('fs');

// 解析参数
const args = process.argv.slice(2);
const params = {};
let currentKey = null;

for (const arg of args) {
  if (arg.startsWith('--')) {
    currentKey = arg.substring(2);
    params[currentKey] = true;
  } else if (currentKey) {
    params[currentKey] = arg;
    currentKey = null;
  }
}

if (!params.agent || !params.command) {
  console.error('Usage: node scripts/rpc-call.js --config <path> --agent <name> --command <cmd> [--args <args>]');
  process.exit(1);
}

async function main() {
  const configPath = params.config || path.join(__dirname, '../server/config/agents.json');
  const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));

  const agentConfig = config.agents[params.agent];
  const launcherConfig = config.launchers[agentConfig.launcher];

  let wsUrl;
  if (launcherConfig.type === 'none' && launcherConfig.url) {
    wsUrl = launcherConfig.url;
  } else {
    console.error(`Unsupported launcher type for RPC: ${launcherConfig.type} (only 'none' with url is supported)`);
    process.exit(1);
  }

  console.log(`Testing RPC connection to ${wsUrl}...`);

  const ws = new WebSocket(wsUrl);

  await new Promise((resolve, reject) => {
    ws.on('open', resolve);
    ws.on('error', reject);
  });

  console.log('Connected. Sending command...');

  let requestParams = {};
  if (params.args) {
    if (params.args.startsWith('{')) {
      try {
        requestParams = JSON.parse(params.args);
      } catch (e) {
        console.warn("Failed to parse args as JSON, treating as raw string", e);
        requestParams = { args: params.args };
      }
    } else if (params.args.includes('=')) {
      // Simple key=value parser
      params.args.split(' ').forEach(kv => {
        const [k, v] = kv.split('=');
        if (k && v) requestParams[k] = v;
      });
    } else {
      requestParams = { args: params.args };
    }
  }

  const request = {
    type: 'control',
    id: Date.now(),
    command: params.command,
    params: requestParams
  };


  ws.send(JSON.stringify(request));

  // 等待响应
  ws.on('message', (data) => {
    const response = JSON.parse(data);
    if (response.id === request.id) {
      console.log('Response:', JSON.stringify(response, null, 2));
      if (response.status === 'ok' || !response.error) {
        process.exit(0);
      } else {
        console.error('RPC Error:', response.error);
        process.exit(1);
      }
    }
  });

  // 超时
  setTimeout(() => {
    console.error('Timeout waiting for RPC response');
    process.exit(1);
  }, 5000);
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});