UNPKG

ai-debug-local-mcp

Version:

๐ŸŽฏ ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

180 lines โ€ข 6.48 kB
/** * NSAccessibility Bridge - Revolutionary Background Interaction * Enables true non-intrusive AI automation using Apple's Accessibility APIs */ import { spawn } from 'child_process'; import { resolve, dirname } from 'path'; import { fileURLToPath } from 'url'; export class AccessibilityBridge { swiftProcess = null; requestId = 1; pendingRequests = new Map(); isRunning = false; async initialize() { if (this.isRunning) return; console.log('๐Ÿš€ Initializing NSAccessibility Bridge...'); // Get current file path and resolve the Swift server path const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const serverPath = resolve(__dirname, '../../swift-accessibility-interaction-server.swift'); this.swiftProcess = spawn(serverPath, { stdio: ['pipe', 'pipe', 'inherit'] }); this.swiftProcess.stdout?.on('data', (data) => { const lines = data.toString().trim().split('\n'); for (const line of lines) { if (line.trim()) { try { const response = JSON.parse(line); const pending = this.pendingRequests.get(response.id); if (pending) { this.pendingRequests.delete(response.id); if (response.success) { pending.resolve(response.result); } else { pending.reject(new Error(response.error)); } } } catch (error) { console.warn('Failed to parse accessibility response:', line); } } } }); this.swiftProcess.on('error', (error) => { console.error('โŒ Accessibility bridge process error:', error); this.isRunning = false; }); this.swiftProcess.on('exit', (code) => { console.log(`๐Ÿ”š Accessibility bridge exited with code ${code}`); this.isRunning = false; }); // Wait for service to be ready await new Promise(resolve => setTimeout(resolve, 1000)); this.isRunning = true; console.log('โœ… NSAccessibility Bridge ready!'); } async sendRequest(action, params = {}) { if (!this.isRunning || !this.swiftProcess) { throw new Error('Accessibility bridge not initialized'); } const id = this.requestId++; const request = { id, action, params }; return new Promise((resolve, reject) => { this.pendingRequests.set(id, { resolve, reject }); const requestString = JSON.stringify(request) + '\n'; this.swiftProcess.stdin.write(requestString); // Timeout after 15 seconds setTimeout(() => { if (this.pendingRequests.has(id)) { this.pendingRequests.delete(id); reject(new Error('Accessibility request timeout')); } }, 15000); }); } /** * Check if accessibility permissions are granted */ async checkPermissions() { try { const result = await this.sendRequest('check_permissions'); return result.hasPermissions || false; } catch (error) { console.error('Failed to check accessibility permissions:', error); return false; } } /** * Get list of available applications */ async getApplications() { try { return await this.sendRequest('get_apps'); } catch (error) { console.error('Failed to get applications:', error); return {}; } } /** * REVOLUTIONARY: Write text to application without focus switching! */ async writeTextToApplication(applicationName, text, windowTitle) { try { console.log(`๐Ÿ“ Writing text to ${applicationName} using NSAccessibility...`); const accessibilityAction = { action: 'set_text', applicationName, text, windowTitle }; const result = await this.sendRequest('accessibility_action', { action_data: accessibilityAction }); console.log('โœ… Background text insertion successful!'); return { success: result.success || false, textFieldsFound: result.textFieldsFound, error: result.error }; } catch (error) { console.error('โŒ Background text insertion failed:', error); return { success: false, error: error instanceof Error ? error.message : String(error) }; } } /** * Get UI elements from application */ async getElements(applicationName, windowTitle) { try { const accessibilityAction = { action: 'get_elements', applicationName, windowTitle }; const result = await this.sendRequest('accessibility_action', { action_data: accessibilityAction }); return { success: true, elements: result.elements || [] }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : String(error) }; } } /** * Cleanup and shutdown the accessibility bridge */ async cleanup() { if (this.swiftProcess && this.isRunning) { try { await this.sendRequest('quit'); } catch (error) { // Ignore quit errors } this.swiftProcess.kill(); this.swiftProcess = null; this.isRunning = false; this.pendingRequests.clear(); console.log('๐Ÿงน Accessibility bridge cleaned up'); } } } // Export singleton instance export const accessibilityBridge = new AccessibilityBridge(); //# sourceMappingURL=accessibility-bridge.js.map