import { writable, derived } from "svelte/store"; import { invoke } from "@tauri-apps/api/core"; export type Theme = "dark" | "light"; export interface HikariConfig { model: string | null; api_key: string | null; custom_instructions: string | null; mcp_servers_json: string | null; auto_granted_tools: string[]; theme: Theme; greeting_enabled: boolean; greeting_custom_prompt: string | null; } const defaultConfig: HikariConfig = { model: null, api_key: null, custom_instructions: null, mcp_servers_json: null, auto_granted_tools: [], theme: "dark", greeting_enabled: true, greeting_custom_prompt: null, }; function createConfigStore() { const config = writable(defaultConfig); const isLoading = writable(true); const isSidebarOpen = writable(false); const saveError = writable(null); async function loadConfig() { isLoading.set(true); try { const savedConfig = await invoke("get_config"); config.set(savedConfig); } catch (error) { console.error("Failed to load config:", error); config.set(defaultConfig); } finally { isLoading.set(false); } } async function saveConfig(newConfig: HikariConfig) { saveError.set(null); try { await invoke("save_config", { config: newConfig }); config.set(newConfig); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); saveError.set(errorMessage); console.error("Failed to save config:", error); throw error; } } async function updateConfig(updates: Partial) { let currentConfig: HikariConfig = defaultConfig; config.subscribe((c) => (currentConfig = c))(); const newConfig = { ...currentConfig, ...updates }; await saveConfig(newConfig); } return { config: { subscribe: config.subscribe }, isLoading: { subscribe: isLoading.subscribe }, isSidebarOpen: { subscribe: isSidebarOpen.subscribe }, saveError: { subscribe: saveError.subscribe }, loadConfig, saveConfig, updateConfig, openSidebar: () => isSidebarOpen.set(true), closeSidebar: () => isSidebarOpen.set(false), toggleSidebar: () => isSidebarOpen.update((open) => !open), setTheme: async (theme: Theme) => { await updateConfig({ theme }); applyTheme(theme); }, addAutoGrantedTool: async (tool: string) => { let currentConfig: HikariConfig = defaultConfig; config.subscribe((c) => (currentConfig = c))(); if (!currentConfig.auto_granted_tools.includes(tool)) { const newTools = [...currentConfig.auto_granted_tools, tool]; await updateConfig({ auto_granted_tools: newTools }); } }, removeAutoGrantedTool: async (tool: string) => { let currentConfig: HikariConfig = defaultConfig; config.subscribe((c) => (currentConfig = c))(); const newTools = currentConfig.auto_granted_tools.filter((t) => t !== tool); await updateConfig({ auto_granted_tools: newTools }); }, getConfig: (): HikariConfig => { let currentConfig: HikariConfig = defaultConfig; config.subscribe((c) => (currentConfig = c))(); return currentConfig; }, }; } export function applyTheme(theme: Theme) { if (typeof document !== "undefined") { document.documentElement.setAttribute("data-theme", theme); } } export const configStore = createConfigStore(); export const isDarkTheme = derived(configStore.config, ($config) => $config.theme === "dark");