/** * Persistent Storage * Electron-store wrapper for application settings */ import { app } from 'electron'; import { randomUUID } from 'node:crypto'; import { resolveSupportedLanguage } from '../../shared/language'; // Lazy-load electron-store (ESM module) // eslint-disable-next-line @typescript-eslint/no-explicit-any let settingsStoreInstance: any = null; /** * Application settings schema */ export interface AppSettings { // General theme: 'light' | 'dark' | 'system'; language: string; startMinimized: boolean; launchAtStartup: boolean; telemetryEnabled: boolean; machineId: string; agentGatewaySessionClientIds: Record; hasReportedInstall: boolean; proxyEnabled: boolean; proxyServer: string; proxyHttpServer: string; proxyHttpsServer: string; proxyAllServer: string; proxyBypassRules: string; // Update updateChannel: 'stable' | 'beta' | 'dev'; autoCheckUpdate: boolean; autoDownloadUpdate: boolean; skippedVersions: string[]; // UI State sidebarCollapsed: boolean; devModeUnlocked: boolean; // Presets selectedBundles: string[]; enabledSkills: string[]; disabledSkills: string[]; } /** * Default settings */ function getSystemLocale(): string { const preferredLanguages = typeof app.getPreferredSystemLanguages === 'function' ? app.getPreferredSystemLanguages() : []; return preferredLanguages[0] || (typeof app.getLocale === 'function' ? app.getLocale() : '') || Intl.DateTimeFormat().resolvedOptions().locale || 'en'; } function createDefaultSettings(): AppSettings { return { // General theme: 'system', language: resolveSupportedLanguage(getSystemLocale()), startMinimized: false, launchAtStartup: false, telemetryEnabled: true, machineId: '', agentGatewaySessionClientIds: {}, hasReportedInstall: false, proxyEnabled: false, proxyServer: '', proxyHttpServer: '', proxyHttpsServer: '', proxyAllServer: '', proxyBypassRules: ';localhost;127.0.0.1;::1', // Update updateChannel: 'stable', autoCheckUpdate: true, autoDownloadUpdate: false, skippedVersions: [], // UI State sidebarCollapsed: false, devModeUnlocked: false, // Presets selectedBundles: ['productivity', 'developer'], enabledSkills: [], disabledSkills: [], }; } /** * Get the settings store instance (lazy initialization) */ async function getSettingsStore() { if (!settingsStoreInstance) { const Store = (await import('electron-store')).default; settingsStoreInstance = new Store({ name: 'settings', defaults: createDefaultSettings(), }); } return settingsStoreInstance; } /** * Get a setting value */ export async function getSetting(key: K): Promise { const store = await getSettingsStore(); return store.get(key); } /** * Set a setting value */ export async function setSetting( key: K, value: AppSettings[K] ): Promise { const store = await getSettingsStore(); store.set(key, value); } let agentGatewaySessionIdMutation: Promise = Promise.resolve(); async function mutateAgentGatewaySessionClientIds( mutation: (current: Record) => Promise | T, ): Promise { const result = agentGatewaySessionIdMutation.then(async () => { const current = await getSetting('agentGatewaySessionClientIds'); return await mutation({ ...current }); }); agentGatewaySessionIdMutation = result.then(() => undefined, () => undefined); return await result; } export function getOrCreateAgentGatewaySessionClientId(workspaceId: string): Promise { return mutateAgentGatewaySessionClientIds(async (current) => { const existing = current[workspaceId]?.trim(); if (existing) return existing; const created = `design-stream-${randomUUID()}`; current[workspaceId] = created; await setSetting('agentGatewaySessionClientIds', current); return created; }); } export function rotateAgentGatewaySessionClientId(workspaceId: string): Promise { return mutateAgentGatewaySessionClientIds(async (current) => { const created = `design-stream-${randomUUID()}`; current[workspaceId] = created; await setSetting('agentGatewaySessionClientIds', current); return created; }); } /** * Get all settings */ export async function getAllSettings(): Promise { const store = await getSettingsStore(); return store.store; } /** * Reset settings to defaults */ export async function resetSettings(): Promise { const store = await getSettingsStore(); store.clear(); } /** * Export settings to JSON */ export async function exportSettings(): Promise { const store = await getSettingsStore(); return JSON.stringify(store.store, null, 2); } /** * Import settings from JSON */ export async function importSettings(json: string): Promise { try { const settings = JSON.parse(json); const store = await getSettingsStore(); store.set(settings); } catch { throw new Error('Invalid settings JSON'); } }