refactor: optimize configuration and tool implementations

- Standardized error handling across tool implementations
- Improved return type consistency for tool execution results
- Simplified configuration parsing and type definitions
- Enhanced type safety for various configuration schemas
- Cleaned up and normalized tool response structures
- Updated SSE and event subscription tool implementations
This commit is contained in:
jango-blockchained
2025-02-04 00:56:45 +01:00
parent 9a02bdaf11
commit bc1dc8278a
65 changed files with 7094 additions and 7675 deletions

View File

@@ -1,92 +1,96 @@
import { exec } from 'child_process';
import { promisify } from 'util';
import { EventEmitter } from 'events';
import { exec } from "child_process";
import { promisify } from "util";
import { EventEmitter } from "events";
const execAsync = promisify(exec);
interface MacOSNotification {
title: string;
message: string;
subtitle?: string;
sound?: boolean;
title: string;
message: string;
subtitle?: string;
sound?: boolean;
}
interface MacOSPermissions {
notifications: boolean;
automation: boolean;
accessibility: boolean;
notifications: boolean;
automation: boolean;
accessibility: boolean;
}
class MacOSIntegration extends EventEmitter {
private permissions: MacOSPermissions;
private permissions: MacOSPermissions;
constructor() {
super();
this.permissions = {
notifications: false,
automation: false,
accessibility: false
};
constructor() {
super();
this.permissions = {
notifications: false,
automation: false,
accessibility: false,
};
}
async initialize(): Promise<void> {
await this.checkPermissions();
await this.registerSystemEvents();
}
async checkPermissions(): Promise<MacOSPermissions> {
try {
// Check notification permissions
const { stdout: notifPerms } = await execAsync(
"osascript -e 'tell application \"System Events\" to get properties'",
);
this.permissions.notifications = notifPerms.includes(
"notifications enabled:true",
);
// Check automation permissions
const { stdout: autoPerms } = await execAsync(
"osascript -e 'tell application \"System Events\" to get UI elements enabled'",
);
this.permissions.automation = autoPerms.includes("true");
// Check accessibility permissions
const { stdout: accessPerms } = await execAsync(
"osascript -e 'tell application \"System Events\" to get processes'",
);
this.permissions.accessibility = !accessPerms.includes("error");
return this.permissions;
} catch (error) {
console.error("Error checking permissions:", error);
return this.permissions;
}
}
async sendNotification(notification: MacOSNotification): Promise<void> {
if (!this.permissions.notifications) {
throw new Error("Notification permission not granted");
}
async initialize(): Promise<void> {
await this.checkPermissions();
await this.registerSystemEvents();
}
async checkPermissions(): Promise<MacOSPermissions> {
try {
// Check notification permissions
const { stdout: notifPerms } = await execAsync(
'osascript -e \'tell application "System Events" to get properties\''
);
this.permissions.notifications = notifPerms.includes('notifications enabled:true');
// Check automation permissions
const { stdout: autoPerms } = await execAsync(
'osascript -e \'tell application "System Events" to get UI elements enabled\''
);
this.permissions.automation = autoPerms.includes('true');
// Check accessibility permissions
const { stdout: accessPerms } = await execAsync(
'osascript -e \'tell application "System Events" to get processes\''
);
this.permissions.accessibility = !accessPerms.includes('error');
return this.permissions;
} catch (error) {
console.error('Error checking permissions:', error);
return this.permissions;
}
}
async sendNotification(notification: MacOSNotification): Promise<void> {
if (!this.permissions.notifications) {
throw new Error('Notification permission not granted');
}
const script = `
display notification "${notification.message}"${notification.subtitle ? ` with subtitle "${notification.subtitle}"` : ''
} with title "${notification.title}"${notification.sound ? ' sound name "default"' : ''
}
const script = `
display notification "${notification.message}"${
notification.subtitle ? ` with subtitle "${notification.subtitle}"` : ""
} with title "${notification.title}"${
notification.sound ? ' sound name "default"' : ""
}
`;
try {
await execAsync(`osascript -e '${script}'`);
} catch (error) {
console.error('Error sending notification:', error);
throw error;
}
try {
await execAsync(`osascript -e '${script}'`);
} catch (error) {
console.error("Error sending notification:", error);
throw error;
}
}
async registerSystemEvents(): Promise<void> {
if (!this.permissions.automation) {
throw new Error("Automation permission not granted");
}
async registerSystemEvents(): Promise<void> {
if (!this.permissions.automation) {
throw new Error('Automation permission not granted');
}
// Monitor system events
const script = `
// Monitor system events
const script = `
tell application "System Events"
set eventList to {}
@@ -110,106 +114,110 @@ class MacOSIntegration extends EventEmitter {
end tell
`;
try {
const { stdout } = await execAsync(`osascript -e '${script}'`);
const events = stdout.split(',').map(e => e.trim());
events.forEach(event => this.emit('system_event', event));
} catch (error) {
console.error('Error monitoring system events:', error);
}
try {
const { stdout } = await execAsync(`osascript -e '${script}'`);
const events = stdout.split(",").map((e) => e.trim());
events.forEach((event) => this.emit("system_event", event));
} catch (error) {
console.error("Error monitoring system events:", error);
}
}
async executeAutomation(script: string): Promise<string> {
if (!this.permissions.automation) {
throw new Error("Automation permission not granted");
}
async executeAutomation(script: string): Promise<string> {
if (!this.permissions.automation) {
throw new Error('Automation permission not granted');
}
try {
const { stdout } = await execAsync(`osascript -e '${script}'`);
return stdout;
} catch (error) {
console.error("Error executing automation:", error);
throw error;
}
}
try {
const { stdout } = await execAsync(`osascript -e '${script}'`);
return stdout;
} catch (error) {
console.error('Error executing automation:', error);
throw error;
}
async getSystemInfo(): Promise<Record<string, any>> {
const info: Record<string, any> = {};
try {
// Get macOS version
const { stdout: version } = await execAsync("sw_vers -productVersion");
info.os_version = version.trim();
// Get hardware info
const { stdout: hardware } = await execAsync(
"system_profiler SPHardwareDataType",
);
info.hardware = this.parseSystemProfile(hardware);
// Get power info
const { stdout: power } = await execAsync("pmset -g batt");
info.power = this.parsePowerInfo(power);
// Get network info
const { stdout: network } = await execAsync(
"networksetup -listallhardwareports",
);
info.network = this.parseNetworkInfo(network);
return info;
} catch (error) {
console.error("Error getting system info:", error);
throw error;
}
}
private parseSystemProfile(output: string): Record<string, any> {
const info: Record<string, any> = {};
const lines = output.split("\n");
for (const line of lines) {
const [key, value] = line.split(":").map((s) => s.trim());
if (key && value) {
info[key.toLowerCase().replace(/\s+/g, "_")] = value;
}
}
async getSystemInfo(): Promise<Record<string, any>> {
const info: Record<string, any> = {};
return info;
}
try {
// Get macOS version
const { stdout: version } = await execAsync('sw_vers -productVersion');
info.os_version = version.trim();
private parsePowerInfo(output: string): Record<string, any> {
const info: Record<string, any> = {};
const lines = output.split("\n");
// Get hardware info
const { stdout: hardware } = await execAsync('system_profiler SPHardwareDataType');
info.hardware = this.parseSystemProfile(hardware);
// Get power info
const { stdout: power } = await execAsync('pmset -g batt');
info.power = this.parsePowerInfo(power);
// Get network info
const { stdout: network } = await execAsync('networksetup -listallhardwareports');
info.network = this.parseNetworkInfo(network);
return info;
} catch (error) {
console.error('Error getting system info:', error);
throw error;
for (const line of lines) {
if (line.includes("Now drawing from")) {
info.power_source = line.includes("Battery") ? "battery" : "ac_power";
} else if (line.includes("%")) {
const matches = line.match(/(\d+)%/);
if (matches) {
info.battery_percentage = parseInt(matches[1]);
}
}
}
private parseSystemProfile(output: string): Record<string, any> {
const info: Record<string, any> = {};
const lines = output.split('\n');
return info;
}
for (const line of lines) {
const [key, value] = line.split(':').map(s => s.trim());
if (key && value) {
info[key.toLowerCase().replace(/\s+/g, '_')] = value;
}
}
private parseNetworkInfo(output: string): Record<string, any> {
const info: Record<string, any> = {};
const lines = output.split("\n");
let currentInterface: string | null = null;
return info;
for (const line of lines) {
if (line.includes("Hardware Port:")) {
currentInterface = line.split(":")[1].trim();
info[currentInterface] = {};
} else if (currentInterface && line.includes("Device:")) {
info[currentInterface].device = line.split(":")[1].trim();
} else if (currentInterface && line.includes("Ethernet Address:")) {
info[currentInterface].mac = line.split(":")[1].trim();
}
}
private parsePowerInfo(output: string): Record<string, any> {
const info: Record<string, any> = {};
const lines = output.split('\n');
for (const line of lines) {
if (line.includes('Now drawing from')) {
info.power_source = line.includes('Battery') ? 'battery' : 'ac_power';
} else if (line.includes('%')) {
const matches = line.match(/(\d+)%/);
if (matches) {
info.battery_percentage = parseInt(matches[1]);
}
}
}
return info;
}
private parseNetworkInfo(output: string): Record<string, any> {
const info: Record<string, any> = {};
const lines = output.split('\n');
let currentInterface: string | null = null;
for (const line of lines) {
if (line.includes('Hardware Port:')) {
currentInterface = line.split(':')[1].trim();
info[currentInterface] = {};
} else if (currentInterface && line.includes('Device:')) {
info[currentInterface].device = line.split(':')[1].trim();
} else if (currentInterface && line.includes('Ethernet Address:')) {
info[currentInterface].mac = line.split(':')[1].trim();
}
}
return info;
}
return info;
}
}
export default MacOSIntegration;
export default MacOSIntegration;