#!/usr/bin/env node

/**
 * Patch cursor-agent CLI to auto-approve MCP tool calls for CI/CD use.
 *
 * This script modifies the cursor-agent source code to bypass the manual
 * approval prompt for MCP tool executions, making it suitable for automated
 * CI/CD pipelines.
 *
 * Usage:
 *   node patch-cursor-mcp.js
 */

import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'fs';
import { join, dirname } from 'path';
import { homedir } from 'os';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

function findLatestCursorAgent() {
  const versionsDir = join(homedir(), '.local/share/cursor-agent/versions');
  
  if (!existsSync(versionsDir)) {
    console.error(`❌ Cursor agent versions directory not found: ${versionsDir}`);
    console.error('   Make sure cursor-agent is installed: curl https://cursor.com/install -fsS | bash');
    process.exit(1);
  }
  
  const versions = readdirSync(versionsDir)
    .map(name => join(versionsDir, name))
    .filter(path => statSync(path).isDirectory());
  
  if (versions.length === 0) {
    console.error(`❌ No cursor-agent versions found in ${versionsDir}`);
    process.exit(1);
  }
  
  // Get the latest version by creation time
  const latestVersion = versions
    .map(path => ({ path, ctime: statSync(path).ctimeMs }))
    .sort((a, b) => b.ctime - a.ctime)[0].path;
  
  return join(latestVersion, 'index.js');
}

function backupFile(filePath) {
  const backupPath = `${filePath  }.backup`;
  
  if (existsSync(backupPath)) {
    console.log(`ℹ️  Backup already exists: ${backupPath}`);
    return backupPath;
  }
  
  const content = readFileSync(filePath, 'utf8');
  writeFileSync(backupPath, content, 'utf8');
  
  console.log(`✅ Backup created: ${backupPath}`);
  return backupPath;
}

function patchMcpApproval(filePath) {
  const content = readFileSync(filePath, 'utf8');
  
  // Check if already patched
  if (content.includes('AUTO-APPROVE MCP TOOLS FOR CI/CD')) {
    console.log('✅ File is already patched!');
    return false;
  }
  
  // Pattern to match the requestApproval call for MCP
  const pattern = /(\s+const result = await this\.pendingDecisionProvider\.requestApproval\(\{\s+type: OperationType\.Mcp,\s+details: \{\s+name: approvalDetails\.name,\s+toolName: approvalDetails\.toolName,\s+providerIdentifier: approvalDetails\.providerIdentifier,\s+args: approvalDetails\.args,\s+\},\s+toolCallId: args\.toolCallId,\s+\}\);)/;
  
  const replacement = `                        // AUTO-APPROVE MCP TOOLS FOR CI/CD
                        const result = { approved: true };
                        /*
                        const result = await this.pendingDecisionProvider.requestApproval({
                            type: OperationType.Mcp,
                            details: {
                                name: approvalDetails.name,
                                toolName: approvalDetails.toolName,
                                providerIdentifier: approvalDetails.providerIdentifier,
                                args: approvalDetails.args,
                            },
                            toolCallId: args.toolCallId,
                        });
                        */`;
  
  const newContent = content.replace(pattern, replacement);
  
  if (newContent === content) {
    console.log('ℹ️  Pattern not found - cursor-agent code structure has changed.');
    console.log('   This is OKAY! Newer versions might not need this patch.');
    console.log('   If auto-approval doesn\'t work, cursor-agent team may have fixed it!');
    return false;
  }
  
  writeFileSync(filePath, newContent, 'utf8');
  return true;
}

function addApprovalKeyLogging(filePath) {
  const content = readFileSync(filePath, 'utf8');
  const lines = content.split('\n');
  
  // Check if already added
  if (lines.some(line => line.includes('🔑 APPROVAL KEY'))) {
    console.log('✅ Approval key logging already enabled!');
    return false;
  }
  
  // Find the line with generateApprovalKey and add logging after it
  let targetLineNum = -1;
  for (let i = 0; i < lines.length; i++) {
    if (lines[i].includes('const approvalKey = generateApprovalKey(serverName, server, this.cwd);')) {
      targetLineNum = i;
      break;
    }
  }
  
  if (targetLineNum === -1) {
    console.log('⚠️  Could not find approval key generation line');
    return false;
  }
  
  // Insert the console.log after the generateApprovalKey line
  const indent = '            ';
  const logLine = `${indent}console.log("🔑 APPROVAL KEY:", serverName, "=>", approvalKey);`;
  lines.splice(targetLineNum + 1, 0, logLine);
  
  writeFileSync(filePath, lines.join('\n'), 'utf8');
  return true;
}

function main() {
  console.log('🔧 Patching cursor-agent for CI/CD MCP usage...\n');
  console.log('ℹ️  Note: This patch is temporary and may not be needed in future versions.\n');
  
  // Find cursor-agent
  const indexFile = findLatestCursorAgent();
  console.log(`📍 Found cursor-agent: ${indexFile}\n`);
  
  // Backup
  backupFile(indexFile);
  console.log();
  
  // Apply patches
  const patchedApproval = patchMcpApproval(indexFile);
  if (patchedApproval) {
    console.log('✅ Patched MCP tool auto-approval');
  }
  console.log();
  
  const patchedLogging = addApprovalKeyLogging(indexFile);
  if (patchedLogging) {
    console.log('✅ Added approval key logging');
  }
  console.log();
  
  if (patchedApproval || patchedLogging) {
    console.log('🎉 cursor-agent is now ready for CI/CD!');
    console.log('\nNext steps:');
    console.log('1. Run: cursor-agent mcp list');
    console.log('2. Copy the approval key shown');
    console.log('3. Add it to ~/.cursor/projects/YOUR_PROJECT/mcp-approvals.json');
    console.log('\n⚠️  If cursor-agent updates break this patch, MCP may work without it.');
  } else {
    console.log('ℹ️  No changes needed - already configured or cursor-agent version doesn\'t need patching!');
  }
}

main();

