/** * Tauri App Service - Desktop implementation */ import { invoke } from '@tauri-apps/api/core' import { AppConfiguration } from '@janhq/core' import type { LogEntry } from './types' import { DefaultAppService } from './default' export class TauriAppService extends DefaultAppService { async factoryReset(): Promise { // Kill background processes and remove data folder // Note: We can't import stopAllModels directly to avoid circular dependency // Instead we'll use the engine manager directly const { EngineManager } = await import('@janhq/core') for (const [, engine] of EngineManager.instance().engines) { const activeModels = await engine.getLoadedModels() if (activeModels) { await Promise.all(activeModels.map((model: string) => engine.unload(model))) } } window.localStorage.clear() await invoke('factory_reset') } async readLogs(): Promise { const logData: string = (await invoke('read_logs')) ?? '' return logData.split('\n').map(this.parseLogLine) } async getJanDataFolder(): Promise { try { const appConfiguration: AppConfiguration | undefined = await window.core?.api?.getAppConfigurations() return appConfiguration?.data_folder } catch (error) { console.error('Failed to get Jan data folder:', error) return undefined } } async relocateJanDataFolder(path: string): Promise { await window.core?.api?.changeAppDataFolder({ newDataFolder: path }) } parseLogLine(line: string): LogEntry { const regex = /^\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]\s(.*)$/ const match = line.match(regex) if (!match) return { timestamp: Date.now(), level: 'info' as 'info' | 'warn' | 'error' | 'debug', target: 'info', message: line ?? '', } as LogEntry const [, date, time, target, levelRaw, message] = match const level = levelRaw.toLowerCase() as 'info' | 'warn' | 'error' | 'debug' return { timestamp: `${date} ${time}`, level, target, message, } } async getServerStatus(): Promise { return await invoke('get_server_status') } async readYaml(path: string): Promise { return await invoke('read_yaml', { path }) } async supportsBlurEffects(): Promise { return await invoke('supports_blur_effects') } }