chore: remove computer use

This commit is contained in:
Simos Mikelatos
2026-06-29 10:30:58 +00:00
parent 35da5d090d
commit 6761f31a56
57 changed files with 14 additions and 6298 deletions

View File

@@ -1,290 +0,0 @@
import { spawn } from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
const IPC_PREFIX = '@@CUAGENT@@';
const TARGET_STATUS_TIMEOUT_MS = 5000;
function getDesktopPath() {
const currentPath = process.env.PATH || '';
const commonPaths = process.platform === 'win32'
? []
: ['/opt/homebrew/bin', '/usr/local/bin', '/usr/bin', '/bin', '/usr/sbin', '/sbin'];
return [...commonPaths, currentPath].filter(Boolean).join(path.delimiter);
}
function getNodeRuntime(isPackaged) {
if (isPackaged && process.versions.electron) {
return { command: process.execPath, env: { ELECTRON_RUN_AS_NODE: '1' } };
}
if (process.env.npm_node_execpath) {
return { command: process.env.npm_node_execpath, env: {} };
}
return { command: 'node', env: {} };
}
function toAgentWsUrl(httpUrl) {
try {
const parsed = new URL(httpUrl);
parsed.protocol = parsed.protocol === 'http:' ? 'ws:' : 'wss:';
parsed.pathname = '/desktop-agent';
parsed.search = '';
parsed.hash = '';
return parsed.toString();
} catch {
return null;
}
}
async function isComputerUseEnabledTarget(httpUrl, apiKey) {
let statusUrl;
try {
statusUrl = new URL('/api/computer-use/status', httpUrl).toString();
} catch {
return false;
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), TARGET_STATUS_TIMEOUT_MS);
try {
const response = await fetch(statusUrl, {
signal: controller.signal,
headers: apiKey ? { 'X-API-Key': apiKey } : undefined,
});
const body = await response.json().catch(() => null);
return response.ok && body?.success !== false && body?.data?.enabled === true;
} catch {
return false;
} finally {
clearTimeout(timeout);
}
}
async function filterEnabledComputerUseTargets(targets, apiKey) {
const checks = await Promise.all(targets.map(async (target) => ({
target,
enabled: await isComputerUseEnabledTarget(target, apiKey),
})));
return checks.filter((item) => item.enabled).map((item) => item.target);
}
/**
* Keeps a Computer Use desktop agent connected to running cloud environments
* while desktop access is enabled.
*/
export class ComputerAgentController {
constructor({ appRoot, settingsPath, isPackaged = false, getRunningEnvironmentUrls, getApiKey, promptConsent, onChange }) {
this.appRoot = appRoot;
this.settingsPath = settingsPath;
this.isPackaged = isPackaged;
this.getRunningEnvironmentUrls = getRunningEnvironmentUrls;
this.getApiKey = getApiKey;
this.promptConsent = promptConsent;
this.onChange = onChange;
this.settings = { enabled: false, consentMode: 'ask' };
this.child = null;
this.connectedUrls = new Set();
this.currentTargets = [];
this.stdoutBuffer = '';
this.lastEvent = null;
this.lastError = null;
}
getSettings() {
return { ...this.settings };
}
getState() {
return {
enabled: this.settings.enabled,
consentMode: this.settings.consentMode,
running: Boolean(this.child),
connectedCount: this.connectedUrls.size,
targetCount: this.currentTargets.length,
targetUrls: [...this.currentTargets],
lastEvent: this.lastEvent,
lastError: this.lastError,
};
}
async loadSettings() {
try {
const raw = await fs.readFile(this.settingsPath, 'utf8');
const stored = JSON.parse(raw);
this.settings = {
enabled: Boolean(stored.enabled),
consentMode: stored.consentMode === 'auto' ? 'auto' : 'ask',
};
} catch {
this.settings = { enabled: false, consentMode: 'ask' };
}
return this.settings;
}
async saveSettings(next) {
this.settings = {
enabled: Boolean(next.enabled),
consentMode: next.consentMode === 'auto' ? 'auto' : 'ask',
};
await fs.mkdir(path.dirname(this.settingsPath), { recursive: true });
await fs.writeFile(this.settingsPath, JSON.stringify(this.settings, null, 2), 'utf8');
await this.sync();
this.onChange?.();
return this.settings;
}
async sync() {
const targets = this.settings.enabled ? (this.getRunningEnvironmentUrls?.() || []) : [];
const enabledTargets = this.settings.enabled ? await filterEnabledComputerUseTargets(targets, this.getApiKey?.() || '') : [];
const wsTargets = enabledTargets.map(toAgentWsUrl).filter(Boolean);
const sameTargets =
wsTargets.length === this.currentTargets.length &&
wsTargets.every((url) => this.currentTargets.includes(url));
if (!this.settings.enabled || wsTargets.length === 0) {
this.stop();
this.currentTargets = [];
this.lastEvent = this.settings.enabled ? 'no-targets' : 'disabled';
return;
}
if (this.child && sameTargets) {
return;
}
this.currentTargets = wsTargets;
this.lastEvent = 'restarting';
this.lastError = null;
this.restart(wsTargets);
}
restart(wsTargets) {
this.stop();
const agentEntry = process.env.CLOUDCLI_COMPUTER_AGENT_ENTRY
|| path.join(this.appRoot, 'dist-server', 'server', 'computer-use-agent.js');
const runtime = getNodeRuntime(this.isPackaged);
this.child = spawn(runtime.command, [agentEntry], {
cwd: this.appRoot,
env: {
...process.env,
...runtime.env,
PATH: getDesktopPath(),
CLOUDCLI_DESKTOP_AGENT_URLS: wsTargets.join(','),
CLOUDCLI_DESKTOP_AGENT_API_KEY: this.getApiKey?.() || '',
CLOUDCLI_COMPUTER_USE_CONSENT_MODE: this.settings.consentMode,
},
stdio: ['pipe', 'pipe', 'pipe'],
windowsHide: true,
});
this.connectedUrls = new Set();
this.child.once('error', (error) => {
console.error('[ComputerAgent] failed to start:', error.message);
this.lastEvent = 'start-error';
this.lastError = error.message;
this.child = null;
this.onChange?.();
});
this.child.stdout?.on('data', (chunk) => this.handleStdout(String(chunk)));
this.child.stderr?.on('data', (chunk) => {
for (const line of String(chunk).split(/\r?\n/)) {
if (line.trim()) {
this.lastError = line.trim();
console.error('[ComputerAgent]', line);
}
}
});
this.child.once('exit', (code) => {
console.log(`[ComputerAgent] exited (code ${code ?? 'null'})`);
this.lastEvent = `exit:${code ?? 'null'}`;
this.child = null;
this.connectedUrls = new Set();
this.onChange?.();
});
this.onChange?.();
}
handleStdout(chunk) {
this.stdoutBuffer += chunk;
const lines = this.stdoutBuffer.split('\n');
this.stdoutBuffer = lines.pop() || '';
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed.startsWith(IPC_PREFIX)) {
if (trimmed) console.log('[ComputerAgent]', trimmed);
continue;
}
let payload;
try {
payload = JSON.parse(trimmed.slice(IPC_PREFIX.length).trim());
} catch {
continue;
}
void this.handleAgentEvent(payload);
}
}
async handleAgentEvent(payload) {
switch (payload.type) {
case 'connected':
this.connectedUrls.add(payload.url);
this.lastEvent = 'connected';
this.lastError = null;
this.onChange?.();
break;
case 'disconnected':
this.connectedUrls.delete(payload.url);
this.lastEvent = 'disconnected';
this.onChange?.();
if (payload.reason && /computer use.*disabled/i.test(payload.reason)) {
void this.sync().catch((error) => {
this.lastError = error instanceof Error ? error.message : 'Failed to sync Computer Use targets.';
this.onChange?.();
});
}
break;
case 'starting':
this.lastEvent = 'starting';
this.lastError = null;
this.onChange?.();
break;
case 'error':
this.lastEvent = 'error';
this.lastError = payload.message || 'Computer agent error.';
this.onChange?.();
break;
case 'consent-request': {
const allow = await this.promptConsent?.(payload.sessionId);
this.sendToChild({ type: 'consent-response', sessionId: payload.sessionId, allow: Boolean(allow) });
break;
}
default:
break;
}
}
sendToChild(message) {
if (this.child?.stdin?.writable) {
this.child.stdin.write(`${IPC_PREFIX} ${JSON.stringify(message)}\n`);
}
}
revokeSession(sessionId) {
this.sendToChild({ type: 'revoke-session', sessionId });
}
stop() {
if (!this.child) return;
const child = this.child;
this.child = null;
this.connectedUrls = new Set();
try { child.kill('SIGTERM'); } catch { /* noop */ }
}
}

View File

@@ -4,10 +4,6 @@ import { ViewHost } from './viewHost.js';
const TITLEBAR_HEIGHT = 44;
const AUTH_TOKEN_STORAGE_KEY = 'auth-token';
// TODO: Re-enable Computer Use menus after fixing the MCP server connection
// between the desktop app and the web UI.
const COMPUTER_USE_MENUS_ENABLED = false;
function isAllowedPermissionOrigin(sourceUrl, controlPlaneUrl) {
try {
const source = new URL(sourceUrl);
@@ -437,17 +433,6 @@ export class DesktopWindowManager {
accelerator: 'CmdOrCtrl+Shift+E',
click: () => void this.actions.showEnvironmentPicker().catch((error) => this.actions.showError('Could not switch environment', error)),
},
{ type: 'separator' },
{
label: 'Services',
visible: COMPUTER_USE_MENUS_ENABLED,
submenu: [
{
label: 'Computer Use',
click: () => void this.showDesktopSettings(),
},
],
},
{
label: 'Diagnostics',
submenu: [

View File

@@ -8,14 +8,6 @@ window.__MOCK_STATE__ = {
shareableWebUrl: 'http://localhost:3001',
localServerRunning: false,
localStartupLogs: [],
computerUse: { enabled: false, consentMode: 'ask', running: false, connectedCount: 0, targetCount: 0 },
computerUsePermissions: {
platform: 'darwin',
supported: true,
accessibility: 'not_granted',
screenRecording: 'not_determined',
message: 'macOS requires Accessibility and Screen Recording for Computer Use.',
},
environments: [
{ id: 'env-api', name: 'api-gateway', subdomain: 'api-gateway', access_url: 'https://api-gateway.cloudcli.ai', status: 'running', region: 'fra1', agent: 'Claude Code' },
{ id: 'env-web', name: 'web-frontend', subdomain: 'web-frontend', access_url: 'https://web-frontend.cloudcli.ai', status: 'stopped', region: 'sfo1', agent: 'Codex' },
@@ -62,7 +54,6 @@ window.__MOCK_STATE__ = {
refreshEnvironments: function () { return Promise.resolve(clone(mockState)); },
refreshActiveTab: function () { return Promise.resolve(clone(mockState)); },
copyDiagnostics: function () { return Promise.resolve(clone(mockState)); },
showComputerAccess: function () { return Promise.resolve(clone(mockState)); },
showEnvironmentPicker: function () { return Promise.resolve(clone(mockState)); },
showLauncher: function () { return Promise.resolve(clone(mockState)); },
showLocalSettings: function () { return Promise.resolve(clone(mockState)); },
@@ -82,23 +73,6 @@ window.__MOCK_STATE__ = {
mockState.desktopSettings[key] = key === 'themeMode' ? value : !!value;
return Promise.resolve(clone(mockState));
},
updateComputerUse: function (settings) {
mockState.computerUse = mockState.computerUse || { enabled: false, consentMode: 'ask', running: false, connectedCount: 0, targetCount: 0 };
if (typeof settings.enabled === 'boolean') mockState.computerUse.enabled = settings.enabled;
if (settings.consentMode === 'auto' || settings.consentMode === 'ask') mockState.computerUse.consentMode = settings.consentMode;
mockState.computerUse.running = mockState.computerUse.enabled;
return Promise.resolve(clone(mockState));
},
requestComputerUsePermission: function (permission) {
mockState.computerUsePermissions = mockState.computerUsePermissions || {};
if (permission === 'accessibility') mockState.computerUsePermissions.accessibility = 'granted';
if (permission === 'screen') mockState.computerUsePermissions.screenRecording = 'granted';
if (permission === 'all') {
mockState.computerUsePermissions.accessibility = 'granted';
mockState.computerUsePermissions.screenRecording = 'granted';
}
return Promise.resolve(clone(mockState));
},
openEnvironment: function (id) {
var env = (mockState.environments || []).filter(function (item) { return item.id === id; })[0];
if (env) {
@@ -189,22 +163,6 @@ window.__MOCK_STATE__ = {
return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
function computerUseStatus(state) {
var computerUse = state && state.computerUse ? state.computerUse : {};
var connectedCount = computerUse.connectedCount || 0;
var environmentLabel = connectedCount + ' environment' + (connectedCount === 1 ? '' : 's');
if (!computerUse.enabled) {
return { label: 'Disabled', tone: 'idle', detail: 'CloudCLI cannot use this computer.' };
}
if (!connectedCount) {
return { label: 'Not connected', tone: 'warn', detail: 'No environment connected.' };
}
if (computerUse.consentMode === 'auto') {
return { label: 'Connected', tone: 'warn', detail: environmentLabel + ' connected. Unattended access is on.' };
}
return { label: 'Connected', tone: 'ok', detail: environmentLabel + ' connected.' };
}
var CC = {
icon: icon,
esc: esc,
@@ -214,7 +172,6 @@ window.__MOCK_STATE__ = {
accountLabel: accountLabel,
localUrl: localUrl,
envCount: envCount,
computerUseStatus: computerUseStatus,
version: VERSION,
logoUrl: LOGO_URL,
platform: 'win',
@@ -352,42 +309,12 @@ window.__MOCK_STATE__ = {
return CC.run('Saved', function () { return bridge.updateSetting(node.key, node.value); });
case 'set-theme-mode':
return CC.run('Saved', function () { return bridge.updateSetting('themeMode', node.value); });
case 'set-computer-mode':
CC.state.computerUse = {
...((CC.state && CC.state.computerUse) || {}),
enabled: true,
consentMode: node.value === 'auto' ? 'auto' : 'ask',
};
return CC.run('Saved', function () {
return bridge.updateComputerUse({
enabled: true,
consentMode: node.value,
});
});
case 'set-computer-enabled':
CC.state.computerUse = {
...((CC.state && CC.state.computerUse) || {}),
enabled: !!node.value,
};
return CC.run('Saved', function () {
var current = (CC.state && CC.state.computerUse) || { consentMode: 'ask' };
return bridge.updateComputerUse({
enabled: !!node.value,
consentMode: current.consentMode === 'auto' ? 'auto' : 'ask',
});
});
case 'computer-permission':
return CC.run('Opening permission settings...', function () {
return bridge.requestComputerUsePermission(node.getAttribute('data-cc-computer-permission'));
});
case 'settings-toggle':
return CC.run('Opening desktop settings...', function () { return bridge.showDesktopSettings(); });
case 'desktop-settings-toggle':
return CC.run('Opening desktop settings...', function () { return bridge.showDesktopSettings(); });
case 'local-settings-toggle':
return CC.run('Opening local settings...', function () { return bridge.showLocalSettings(); });
case 'computer-settings-toggle':
return CC.run('Opening desktop settings...', function () { return bridge.showDesktopSettings(); });
case 'settings-close':
return CC.closeSheet();
case 'dashboard':
@@ -541,62 +468,6 @@ window.__MOCK_STATE__ = {
);
};
function permissionLabel(value) {
if (value === 'granted') return 'Granted';
if (value === 'denied' || value === 'restricted') return 'Needs attention';
if (value === 'not_applicable') return 'Not required';
return 'Not granted';
}
function permissionTone(value) {
if (value === 'granted' || value === 'not_applicable') return 'ok';
if (value === 'denied' || value === 'restricted') return 'warn';
return 'idle';
}
// TODO: Re-enable Computer Use menus after fixing the MCP server connection
// between the desktop app and the web UI.
var COMPUTER_USE_MENUS_ENABLED = false;
function renderComputerPermissionRow(key, label, detail, status) {
return '<div class="cc-permission-row">' +
'<div><div class="cc-permission-title">' + CC.esc(label) + '</div><div class="cc-permission-detail">' + CC.esc(detail) + '</div></div>' +
'<div class="cc-permission-actions"><span class="badge ' + permissionTone(status) + '">' + CC.esc(permissionLabel(status)) + '</span>' +
(status === 'granted' || status === 'not_applicable'
? ''
: '<button class="btn sm" data-cc-action="computer-permission" data-cc-computer-permission="' + CC.esc(key) + '">Open settings</button>') +
'</div>' +
'</div>';
}
function renderComputerPermissions(state) {
var permissions = state.computerUsePermissions || {};
if (!permissions.supported) {
return '<div class="cc-note">' + CC.esc(permissions.message || 'No additional OS permission setup is required from CloudCLI on this platform.') + '</div>';
}
return '<div class="cc-note">' + CC.esc(permissions.message || 'Grant the required OS permissions before approving agent control.') + '</div>' +
renderComputerPermissionRow('accessibility', 'Accessibility', 'Allows CloudCLI to click, type, and use accessibility actions.', permissions.accessibility) +
renderComputerPermissionRow('screen', 'Screen Recording', 'Allows CloudCLI to capture screenshots for agent observation.', permissions.screenRecording);
}
CC.buildComputerUseSection = function (state) {
var computerUse = state.computerUse || {};
var status = computerUseStatus(state);
var body =
'<div class="cc-surface">' +
'<label class="cc-toggle"><input type="checkbox" data-cc-computer-enabled="true"' + (computerUse.enabled ? ' checked' : '') + '><span><b>Enable Computer Use</b><br>Let CloudCLI use the computer. Agents cannot act until you approve a session.</span></label>' +
'<div class="cc-row2"><span class="badge ' + CC.esc(status.tone) + '">' + CC.esc(status.label) + '</span><span class="cc-meta">' + CC.esc(status.detail) + '</span><button class="btn sm" data-cc-action="refresh-environments">' + CC.icon('refresh', 14) + 'Refresh / relink</button></div>';
if (computerUse.enabled) {
body += '<div class="cc-permissions">' + renderComputerPermissions(state) + '</div>';
body += '<div class="cc-choice-group">' +
CC.renderRadioOption('computer-access-mode', 'ask', computerUse.consentMode !== 'auto', 'Ask before each session', 'Agents can request control, but you approve every session.') +
CC.renderRadioOption('computer-access-mode', 'auto', computerUse.consentMode === 'auto', 'Unattended access', 'Trusted agents can use this computer without a local approval prompt.') +
'</div>';
}
body += '</div>';
return CC.renderSection('COMPUTER USE', 'Control how agents can use this computer', body);
};
CC.renderLocalSettings = function () {
var state = CC.state || {};
var sections = [
@@ -612,13 +483,9 @@ window.__MOCK_STATE__ = {
};
CC.renderDesktopSettings = function () {
var state = CC.state || {};
var sections = [
CC.buildThemeSection(state),
CC.buildThemeSection(CC.state || {}),
];
if (COMPUTER_USE_MENUS_ENABLED) {
sections.push(CC.buildComputerUseSection(state));
}
CC.renderSheet('Desktop Settings', 'Manage the desktop app appearance.', sections);
};
@@ -681,15 +548,6 @@ window.__MOCK_STATE__ = {
CC.act('set-theme-mode', { value: theme.value });
return;
}
var computerMode = event.target.closest('[name="computer-access-mode"]');
if (computerMode) {
CC.act('set-computer-mode', { value: computerMode.value });
return;
}
var computerEnabled = event.target.closest('[data-cc-computer-enabled]');
if (computerEnabled) {
CC.act('set-computer-enabled', { value: computerEnabled.checked });
}
});
document.addEventListener('keydown', function (event) {

View File

@@ -1,10 +1,9 @@
import { app, BrowserWindow, clipboard, dialog, ipcMain, session, shell, systemPreferences } from 'electron';
import { app, BrowserWindow, clipboard, dialog, ipcMain, session, shell } from 'electron';
import { spawn } from 'node:child_process';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { CloudController } from './cloud.js';
import { ComputerAgentController } from './computerAgent.js';
import { DesktopWindowManager } from './desktopWindow.js';
import { DesktopNotificationsController } from './desktopNotifications.js';
import { LocalServerController } from './localServer.js';
@@ -30,7 +29,6 @@ let activeTarget = { kind: 'launcher', name: APP_NAME, url: null };
let desktopWindow = null;
let localServer = null;
let cloud = null;
let computerAgent = null;
let desktopNotifications = null;
let isQuitting = false;
let isRefreshingCloud = false;
@@ -63,10 +61,6 @@ function getSettingsPath() {
return path.join(app.getPath('userData'), 'desktop-settings.json');
}
function getComputerUseSettingsPath() {
return path.join(app.getPath('userData'), 'computer-use-settings.json');
}
function getDesktopNotificationsSettingsPath() {
return path.join(app.getPath('userData'), 'desktop-notifications-settings.json');
}
@@ -78,23 +72,6 @@ function getRunningEnvironmentUrls() {
.filter(Boolean);
}
async function promptComputerUseConsent(sessionId) {
const { response } = await dialog.showMessageBox(desktopWindow?.getMainWindow() || undefined, {
type: 'warning',
buttons: ['Allow this session', 'Deny'],
defaultId: 0,
cancelId: 1,
title: 'Computer Use request',
message: 'An agent wants to control this computer',
detail: [
'A cloud agent is requesting control of your mouse, keyboard, and screen for this session.',
'Approval lasts for this session only. You can stop it any time from the Computer panel.',
sessionId ? `\nSession: ${sessionId}` : '',
].join('\n'),
});
return response === 0;
}
function getDisplayTargetName() {
return activeTarget?.name || APP_NAME;
}
@@ -151,66 +128,10 @@ function getDesktopState() {
tabs: tabs.getSerializableTabs(),
activeTabId: tabs.activeTabId,
environments: cloud.getEnvironments().map(serializeEnvironment),
computerUse: computerAgent?.getState() || { enabled: false, consentMode: 'ask', running: false, connectedCount: 0, targetCount: 0 },
desktopNotifications: desktopNotifications?.getState() || { enabled: false, supported: false, connectedCount: 0, targetCount: 0 },
computerUsePermissions: getComputerUsePermissions(),
};
}
function getComputerUsePermissions() {
if (process.platform !== 'darwin') {
return {
platform: process.platform,
supported: false,
accessibility: 'not_applicable',
screenRecording: 'not_applicable',
message: 'No OS permission onboarding is required from CloudCLI on this platform.',
};
}
let accessibility;
let screenRecording;
try {
accessibility = systemPreferences.isTrustedAccessibilityClient(false) ? 'granted' : 'not_granted';
} catch {
accessibility = 'unknown';
}
try {
screenRecording = systemPreferences.getMediaAccessStatus('screen');
} catch {
screenRecording = 'unknown';
}
return {
platform: 'darwin',
supported: true,
accessibility,
screenRecording,
message: accessibility === 'granted' && screenRecording === 'granted'
? 'macOS permissions are granted.'
: 'macOS requires Accessibility and Screen Recording for Computer Use.',
};
}
async function requestComputerUsePermission(permission) {
if (process.platform !== 'darwin') {
return getDesktopState();
}
if (permission === 'accessibility') {
systemPreferences.isTrustedAccessibilityClient(true);
} else if (permission === 'screen') {
await shell.openExternal('x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture');
} else if (permission === 'all') {
systemPreferences.isTrustedAccessibilityClient(true);
await shell.openExternal('x-apple.systempreferences:com.apple.preference.security?Privacy_ScreenCapture');
} else {
throw new Error(`Unknown Computer Use permission: ${permission}`);
}
return getDesktopState();
}
async function openExternalUrl(url) {
if (String(url).startsWith(CALLBACK_PROTOCOL + "://")) {
await handleDeepLink(url);
@@ -316,8 +237,6 @@ function getDiagnosticsText() {
cloudEnvironmentCount: cloud.getEnvironments().length,
cloudRunningEnvironmentCount: getRunningEnvironmentUrls().length,
cloudAuthState: cloud.getAuthState(),
computerUse: computerAgent?.getState() || null,
computerUseSettingsPath: getComputerUseSettingsPath(),
cloudAccountPath: getStorePath(),
controlPlaneUrl: CLOUDCLI_CONTROL_PLANE_URL,
}, null, 2);
@@ -332,22 +251,6 @@ async function copyDiagnostics() {
});
}
async function showComputerAccess() {
await desktopWindow?.showDesktopSettings();
return getDesktopState();
}
async function updateComputerUse(settings) {
const current = computerAgent?.getSettings() || { enabled: false, consentMode: 'ask' };
const next = {
enabled: typeof settings?.enabled === 'boolean' ? settings.enabled : current.enabled,
consentMode: settings?.consentMode === 'auto' ? 'auto' : 'ask',
};
await computerAgent?.saveSettings(next);
syncDesktopState();
return getDesktopState();
}
async function refreshCloudEnvironments({ showErrors = false } = {}) {
isRefreshingCloud = true;
syncDesktopState();
@@ -370,7 +273,6 @@ async function refreshCloudEnvironments({ showErrors = false } = {}) {
throw error;
} finally {
isRefreshingCloud = false;
void computerAgent?.sync().catch((error) => console.error('[ComputerAgent] sync failed:', error?.message || error));
void desktopNotifications?.sync().catch((error) => console.error('[DesktopNotifications] sync failed:', error?.message || error));
syncDesktopState();
}
@@ -852,16 +754,10 @@ function registerIpcHandlers() {
await desktopWindow.showLauncher();
return getDesktopState();
});
ipcMain.handle('cloudcli-desktop:show-computer-access', async () => {
await showComputerAccess();
return getDesktopState();
});
ipcMain.handle('cloudcli-desktop:update-computer-use', async (_event, settings) => updateComputerUse(settings));
ipcMain.handle('cloudcli-desktop:update-desktop-notifications', async (_event, settings) => {
await desktopNotifications?.saveSettings(settings);
return getDesktopState();
});
ipcMain.handle('cloudcli-desktop:request-computer-use-permission', async (_event, permission) => requestComputerUsePermission(permission));
ipcMain.handle('cloudcli-desktop:show-desktop-settings', async () => desktopWindow.showDesktopSettings());
ipcMain.handle('cloudcli-desktop:show-local-settings', async () => desktopWindow.showLocalSettings());
ipcMain.handle('cloudcli-desktop:close-settings-window', async () => {
@@ -899,7 +795,6 @@ function registerAppEvents() {
});
app.on('before-quit', () => {
computerAgent?.stop();
desktopNotifications?.stop();
});
@@ -951,7 +846,6 @@ async function createDesktopWindow() {
openCloudDashboard,
refreshCloudEnvironments: () => refreshCloudEnvironments({ showErrors: true }),
setActiveTarget,
showComputerAccess,
showEnvironmentPicker,
showError,
startEnvironment,
@@ -1017,15 +911,6 @@ async function bootstrap() {
callbackUrl: CALLBACK_URL,
onChange: syncDesktopState,
});
computerAgent = new ComputerAgentController({
appRoot: getAppRoot(),
settingsPath: getComputerUseSettingsPath(),
isPackaged: app.isPackaged,
getRunningEnvironmentUrls,
getApiKey: () => cloud.getAccount()?.apiKey || '',
promptConsent: promptComputerUseConsent,
onChange: syncDesktopState,
});
desktopNotifications = new DesktopNotificationsController({
settingsPath: getDesktopNotificationsSettingsPath(),
appVersion: app.getVersion(),
@@ -1042,7 +927,6 @@ async function bootstrap() {
await localServer.loadDesktopSettings();
await cloud.loadCloudAccount();
await computerAgent.loadSettings();
await desktopNotifications.loadSettings();
registerProtocolHandler();

View File

@@ -44,10 +44,7 @@ if (window.location.protocol === 'file:') {
refreshActiveTab: () => ipcRenderer.invoke('cloudcli-desktop:reload-active-tab'),
showEnvironmentPicker: () => ipcRenderer.invoke('cloudcli-desktop:show-environment-picker'),
showLauncher: () => ipcRenderer.invoke('cloudcli-desktop:show-launcher'),
showComputerAccess: () => ipcRenderer.invoke('cloudcli-desktop:show-computer-access'),
showLocalSettings: () => ipcRenderer.invoke('cloudcli-desktop:show-local-settings'),
updateComputerUse: (settings) => ipcRenderer.invoke('cloudcli-desktop:update-computer-use', settings),
requestComputerUsePermission: (permission) => ipcRenderer.invoke('cloudcli-desktop:request-computer-use-permission', permission),
showDesktopSettings: () => ipcRenderer.invoke('cloudcli-desktop:show-desktop-settings'),
closeSettingsWindow: () => ipcRenderer.invoke('cloudcli-desktop:close-settings-window'),
showActiveEnvironmentActionsMenu: () => ipcRenderer.invoke('cloudcli-desktop:show-active-environment-actions-menu'),