import { useCallback, useEffect, useState } from 'react'; import { Download, Loader2, RefreshCw } from 'lucide-react'; import { Button } from '../../../../../shared/view/ui'; import { authenticatedFetch } from '../../../../../utils/api'; import SettingsCard from '../../SettingsCard'; import SettingsRow from '../../SettingsRow'; import SettingsSection from '../../SettingsSection'; import SettingsToggle from '../../SettingsToggle'; type ComputerUseSettings = { enabled: boolean; }; type ComputerUseStatus = { enabled: boolean; runtime: 'cloud' | 'local'; available: boolean; desktopAgentConnected?: boolean; desktopAgentCount?: number; nutInstalled: boolean; screenshotInstalled: boolean; installInProgress: boolean; message: string; }; async function readJson(response: Response): Promise { const data = await response.json(); if (!response.ok || data.success === false) { throw new Error(data.error || data.details || `Request failed (${response.status})`); } return data as T; } export default function ComputerUseSettingsTab() { const [settings, setSettings] = useState({ enabled: false }); const [status, setStatus] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [isInstalling, setIsInstalling] = useState(false); const [error, setError] = useState(null); const loadState = useCallback(async () => { setError(null); const [settingsResponse, statusResponse] = await Promise.all([ authenticatedFetch('/api/computer-use/settings'), authenticatedFetch('/api/computer-use/status'), ]); const settingsData = await readJson<{ data: { settings: ComputerUseSettings } }>(settingsResponse); const statusData = await readJson<{ data: ComputerUseStatus }>(statusResponse); setSettings(settingsData.data.settings); setStatus(statusData.data); }, []); const refreshState = useCallback(async () => { setIsLoading(true); try { await loadState(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load Computer Use settings'); } finally { setIsLoading(false); } }, [loadState]); useEffect(() => { void refreshState(); }, [refreshState]); const updateSettings = async (nextSettings: Partial) => { setIsSaving(true); setError(null); try { const response = await authenticatedFetch('/api/computer-use/settings', { method: 'PUT', body: JSON.stringify(nextSettings), }); const data = await readJson<{ data: { settings: ComputerUseSettings } }>(response); setSettings(data.data.settings); window.dispatchEvent(new Event('computerUseSettingsChanged')); await loadState(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save Computer Use settings'); } finally { setIsSaving(false); } }; const installRuntime = async () => { setIsInstalling(true); setError(null); try { const response = await authenticatedFetch('/api/computer-use/runtime/install', { method: 'POST' }); await readJson(response); await loadState(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to install Computer Use runtime'); } finally { setIsInstalling(false); } }; const isCloud = status?.runtime === 'cloud'; const effectiveEnabled = isCloud ? status?.enabled === true : settings.enabled; const showCloudDesktopAccess = Boolean(isCloud && effectiveEnabled); const needsRuntime = Boolean(effectiveEnabled && !isCloud && status && (!status.nutInstalled || !status.screenshotInstalled)); const desktopAgentCount = status?.desktopAgentCount ?? (status?.desktopAgentConnected ? 1 : 0); const modeDescription = isCloud ? 'Let cloud agents request access to your own computer through CloudCLI Desktop.' : 'Let local agents request access to this computer.'; return (
{isCloud ? 'A cloud agent can use your desktop only after you approve the request in CloudCLI Desktop. Stop ends access immediately.' : 'Agents can use your desktop only while you grant control from the Computer tab. Stop ends access immediately.'}
{effectiveEnabled && (
{isCloud ? 'Keep CloudCLI Desktop open on the computer you want agents to use.' : 'Open the Computer tab to review requests, grant control, or stop a session.'}
)}
void updateSettings({ enabled: value })} ariaLabel="Enable Computer Use" disabled={isLoading || isSaving} /> {showCloudDesktopAccess && (
{status?.desktopAgentConnected ? `${desktopAgentCount} linked` : 'Not linked'}
)} {(needsRuntime || showCloudDesktopAccess || error) && (
{showCloudDesktopAccess && !status?.desktopAgentConnected && (
To link this computer
  1. Open CloudCLI Desktop on the computer you want agents to use.
  2. Connect the same CloudCLI account used for this cloud environment.
  3. Open Desktop Settings and turn on Computer Use.
  4. Keep the desktop app running. This status changes to Desktop linked automatically.
)} {showCloudDesktopAccess && status?.desktopAgentConnected && (
{desktopAgentCount > 1 ? `${desktopAgentCount} desktops are linked. Agents will use one available desktop; stop Computer Use on any desktop you do not want agents to control.` : 'CloudCLI Desktop is linked. Approval prompts will appear there when an agent requests desktop access.'}
)} {needsRuntime && (
Desktop runtime required

{status?.message || 'Install the desktop control runtime needed to capture the screen and drive input.'}

Control lib: {status?.nutInstalled ? 'installed' : 'missing'} Screen capture: {status?.screenshotInstalled ? 'installed' : 'missing'}
)} {error && (
{error}
)}
)}
); }