natural-command-test.js•5.85 kB
import robot from 'robotjs';
import { spawn } from 'child_process';
import path from 'path';
import { windowManager } from 'node-window-manager';
import { parseNaturalLanguage } from '../commands/cursor-commands.js';
const DEFAULT_CURSOR_PATH = path.join(process.env.LOCALAPPDATA || '', 'Programs', 'cursor', 'Cursor.exe');
async function findCursorWindow() {
const windows = windowManager.getWindows();
return windows.find(w => w.getTitle().includes('Cursor'));
}
async function ensureCursorFocus(cursorWindow) {
// Get currently active window
const windows = windowManager.getWindows();
const activeWindow = windows.find(w => w.getTitle().includes('Cursor'));
// Check if Cursor is already focused
if (activeWindow) {
return true;
}
// If not focused, try to restore focus
console.log('Restoring Cursor window focus...');
cursorWindow.bringToTop();
cursorWindow.show();
cursorWindow.restore();
// Wait for focus change
await new Promise(resolve => setTimeout(resolve, 500));
// Verify focus was restored
const newWindows = windowManager.getWindows();
const newActiveWindow = newWindows.find(w => w.getTitle().includes('Cursor'));
return !!newActiveWindow;
}
async function typeText(text, cursorWindow) {
for (const char of text) {
// Ensure focus before each keystroke
if (!await ensureCursorFocus(cursorWindow)) {
console.log('Failed to maintain Cursor window focus');
throw new Error('Lost window focus');
}
// Handle uppercase letters
if (char >= 'A' && char <= 'Z') {
robot.keyToggle('shift', 'down');
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyTap(char.toLowerCase());
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyToggle('shift', 'up');
await new Promise(resolve => setTimeout(resolve, 50));
}
// Handle special characters
else if (char === ':') {
robot.keyToggle('shift', 'down');
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyTap(';'); // On most keyboards, shift+; gives :
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyToggle('shift', 'up');
await new Promise(resolve => setTimeout(resolve, 50));
}
// Handle spaces
else if (char === ' ') {
robot.keyTap('space');
await new Promise(resolve => setTimeout(resolve, 50));
}
// Handle normal lowercase letters
else {
robot.keyTap(char);
await new Promise(resolve => setTimeout(resolve, 50));
}
}
}
async function executeCommand(naturalCommand) {
try {
console.log('Launching Cursor...');
const cursorProcess = spawn(DEFAULT_CURSOR_PATH, [], {
detached: false,
stdio: ['ignore', 'pipe', 'pipe'],
windowsHide: false
});
// Wait for Cursor to start
console.log('Waiting for Cursor to initialize...');
await new Promise(resolve => setTimeout(resolve, 3000));
// Find the Cursor window
const cursorWindow = await findCursorWindow();
if (!cursorWindow) {
throw new Error('Could not find Cursor window');
}
// Parse the natural language command
const commandRequest = parseNaturalLanguage(naturalCommand);
if (!commandRequest) {
throw new Error(`Could not understand command: ${naturalCommand}`);
}
// Initial focus
console.log('Focusing Cursor window...');
if (!await ensureCursorFocus(cursorWindow)) {
throw new Error('Failed to focus Cursor window');
}
console.log('Sending Ctrl+Shift+P...');
// Press Ctrl+Shift+P using robotjs
robot.keyToggle('control', 'down');
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyToggle('shift', 'down');
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyToggle('p', 'down');
await new Promise(resolve => setTimeout(resolve, 50));
// Release in reverse order with delays
robot.keyToggle('p', 'up');
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyToggle('shift', 'up');
await new Promise(resolve => setTimeout(resolve, 50));
robot.keyToggle('control', 'up');
await new Promise(resolve => setTimeout(resolve, 50));
console.log('Command palette shortcut sent!');
// Wait for command palette to appear
await new Promise(resolve => setTimeout(resolve, 500));
// Type the command with focus checks
console.log('Typing command:', commandRequest.command);
await typeText(commandRequest.command, cursorWindow);
// Wait briefly after typing
await new Promise(resolve => setTimeout(resolve, 500));
// Ensure focus before Enter
if (!await ensureCursorFocus(cursorWindow)) {
throw new Error('Lost window focus before pressing Enter');
}
// Press Enter
console.log('Pressing Enter...');
robot.keyTap('enter');
// Keep process alive briefly to observe result
await new Promise(resolve => setTimeout(resolve, 2000));
// Cleanup
console.log('Cleaning up...');
cursorProcess.kill();
}
catch (error) {
console.error('Test failed:', error);
process.exit(1);
}
}
// Example usage
const command = process.argv[2] || 'open cline';
console.log('Executing natural language command:', command);
executeCommand(command).catch(error => {
console.error('Unhandled error:', error);
process.exit(1);
});