feat: add troubleshooting settings with open app data and reset workspace

Add a Troubleshooting section under a Support nav group in Settings:

- Open App Data Folder: reveals the user-data directory in the OS file
  explorer via shell.openPath.
- Reset Local Workspace: destructive action that deletes workspace.json
  and scratchpad contents, clears the in-memory cache, and reseeds
  defaults. Auth secrets are preserved. Requires two-step confirmation.

New IPC channels, ElectronApi methods, and preload bridge added for
openAppDataFolder and resetLocalWorkspace. Existing electron mock in
tests updated to include shell.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-25 21:50:16 +01:00
co-authored by Copilot
parent 5123f9163c
commit 2e3175934d
8 changed files with 168 additions and 5 deletions
+25 -2
View File
@@ -1,7 +1,8 @@
import { EventEmitter } from 'node:events';
import { basename } from 'node:path';
import { rm } from 'node:fs/promises';
import { basename, dirname } from 'node:path';
import { dialog } from 'electron';
import { dialog, shell } from 'electron';
import type {
AgentActivityEvent,
@@ -159,6 +160,28 @@ export class EryxAppService extends EventEmitter<AppServiceEvents> {
void this.secretStore;
}
async openAppDataFolder(): Promise<void> {
const appDataPath = dirname(this.workspaceRepository.filePath);
await shell.openPath(appDataPath);
}
async resetLocalWorkspace(): Promise<WorkspaceState> {
await this.sidecar.dispose();
try {
await rm(this.workspaceRepository.filePath, { force: true });
await rm(this.workspaceRepository.scratchpadPath, { recursive: true, force: true });
} catch (error) {
console.error('[aryx reset]', error);
}
this.workspace = undefined;
this.sidecarCapabilities = undefined;
this.didScheduleInitialProjectGitRefresh = false;
return this.loadWorkspace();
}
async addProject(): Promise<WorkspaceState> {
const workspace = await this.loadWorkspace();
const result = await dialog.showOpenDialog({
+2
View File
@@ -96,6 +96,8 @@ export function registerIpcHandlers(window: BrowserWindow, service: EryxAppServi
ipcMain.handle(ipcChannels.selectProject, (_event, projectId?: string) => service.selectProject(projectId));
ipcMain.handle(ipcChannels.selectPattern, (_event, patternId?: string) => service.selectPattern(patternId));
ipcMain.handle(ipcChannels.selectSession, (_event, sessionId?: string) => service.selectSession(sessionId));
ipcMain.handle(ipcChannels.openAppDataFolder, () => service.openAppDataFolder());
ipcMain.handle(ipcChannels.resetLocalWorkspace, () => service.resetLocalWorkspace());
service.on('workspace-updated', (workspace) => {
window.webContents.send(ipcChannels.workspaceUpdated, workspace);