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
JavaScript
/**
* 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