import React, { useState, useEffect, useCallback } from 'react'; import { SessionCreationForm } from './components/SessionCreationForm'; import { SessionProgressMonitor } from './components/SessionProgressMonitor'; import type { HostedSessionConfig } from '../../../packages/domain/entities/HostedSessionConfig'; interface SessionProgress { sessionId: string; currentStep: number; state: string; completedSteps: number[]; hasError: boolean; errorMessage: string | null; } interface PermissionStatus { accessibility: boolean; screenRecording: boolean; platform: string; } export function App() { const [sessionId, setSessionId] = useState(null); const [progress, setProgress] = useState(null); const [isRunning, setIsRunning] = useState(false); const [permissionStatus, setPermissionStatus] = useState(null); const [permissionChecking, setPermissionChecking] = useState(true); const [missingPermissions, setMissingPermissions] = useState([]); const checkPermissions = useCallback(async () => { if (!window.electronAPI) return; setPermissionChecking(true); try { const result = await window.electronAPI.checkPermissions(); setPermissionStatus(result.status); setMissingPermissions(result.missingPermissions); } catch (error) { console.error('Failed to check permissions:', error); } finally { setPermissionChecking(false); } }, []); useEffect(() => { // Check permissions on app start checkPermissions(); if (window.electronAPI) { window.electronAPI.onSessionProgress((newProgress: SessionProgress) => { setProgress(newProgress); if (newProgress.state === 'COMPLETED' || newProgress.state === 'FAILED' || newProgress.state === 'STOPPED_AT_STEP_18') { setIsRunning(false); } }); } }, [checkPermissions]); const handleOpenPermissionSettings = async (pane?: 'accessibility' | 'screenRecording') => { if (!window.electronAPI) return; await window.electronAPI.openPermissionSettings(pane); }; const handleRequestAccessibility = async () => { if (!window.electronAPI) return; await window.electronAPI.requestAccessibility(); // Recheck permissions after request setTimeout(checkPermissions, 500); }; const handleStartAutomation = async (config: HostedSessionConfig) => { // Recheck permissions before starting await checkPermissions(); if (missingPermissions.length > 0) { alert(`Cannot start automation: Missing permissions: ${missingPermissions.join(', ')}`); return; } setIsRunning(true); const result = await window.electronAPI.startAutomation(config); if (result.success && result.sessionId) { setSessionId(result.sessionId); } else { setIsRunning(false); if (result.permissionError) { // Update permission status await checkPermissions(); alert(`Permission Error: ${result.error}`); } else { alert(`Failed to start automation: ${result.error}`); } } }; const handleStopAutomation = async () => { if (sessionId) { const result = await window.electronAPI.stopAutomation(sessionId); if (result.success) { setIsRunning(false); setProgress(prev => prev ? { ...prev, state: 'STOPPED', hasError: false, errorMessage: 'User stopped automation' } : null); } else { alert(`Failed to stop automation: ${result.error}`); } } }; const isMacOS = permissionStatus?.platform === 'darwin'; const hasAllPermissions = missingPermissions.length === 0; return (

GridPilot Companion

Hosted Session Automation POC

{/* Permission Banner */} {isMacOS && !permissionChecking && !hasAllPermissions && (

⚠️ Missing Permissions

GridPilot requires macOS permissions to control your computer for automation. Please grant the following permissions:

    {!permissionStatus?.accessibility && (
  • Accessibility: Required for keyboard and mouse control
  • )} {!permissionStatus?.screenRecording && (
  • Screen Recording: Required for screen capture and window detection
  • )}
{!permissionStatus?.accessibility && ( )} {!permissionStatus?.accessibility && ( )} {!permissionStatus?.screenRecording && ( )}

After granting permissions in System Preferences, click "Recheck Permissions" or restart the app.

)} {/* Permission Status Indicator */} {isMacOS && !permissionChecking && hasAllPermissions && (
All permissions granted - Ready for automation
)} {isRunning && ( )}
); }