import { defineStore } from 'pinia' import { ref, computed } from 'vue' import type { AIContextCategory } from '@/types/aiui-protocol' const STORAGE_KEY = 'archipelago-ai-permissions' export interface AIPermissionCategory { id: AIContextCategory label: string description: string icon: string group: string } export const AI_PERMISSION_CATEGORIES: AIPermissionCategory[] = [ { id: 'apps', label: 'Installed Apps', description: 'App names, status, and health — no credentials or config details', icon: 'M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z', group: 'Node Data', }, { id: 'system', label: 'System Stats', description: 'CPU, RAM, disk usage — no file paths or IP addresses', icon: 'M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z', group: 'Node Data', }, { id: 'network', label: 'Network Status', description: 'Connection status, peer count — no IP addresses or keys', icon: 'M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01', group: 'Node Data', }, { id: 'bitcoin', label: 'Bitcoin Node', description: 'Block height, sync progress, mempool stats — no wallet keys', icon: 'M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z', group: 'Node Data', }, { id: 'media', label: 'Media Libraries', description: 'Local media libraries — film, music, podcast titles and metadata, no file paths', icon: 'M7 4v16M17 4v16M3 8h4m10 0h4M3 12h18M3 16h4m10 0h4M4 20h16a1 1 0 001-1V5a1 1 0 00-1-1H4a1 1 0 00-1 1v14a1 1 0 001 1z', group: 'Media & Files', }, { id: 'files', label: 'File Names', description: 'Folder and file names in Cloud — no file contents', icon: 'M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z', group: 'Media & Files', }, { id: 'notes', label: 'Documents & Notes', description: 'Document and note titles — no contents', icon: 'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', group: 'Media & Files', }, { id: 'search', label: 'Web Search', description: 'Web search via your private SearXNG instance', icon: 'M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z', group: 'AI & Search', }, { id: 'ai-local', label: 'Local AI Models', description: 'Local AI models via Ollama — model names and availability', icon: 'M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z', group: 'AI & Search', }, { id: 'wallet', label: 'Wallet Overview', description: 'Balance, channel count — no private keys, seeds, or addresses', icon: 'M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z', group: 'Financial', }, ] export const useAIPermissionsStore = defineStore('aiPermissions', () => { const enabled = ref>(loadFromStorage()) function loadFromStorage(): Set { try { const stored = localStorage.getItem(STORAGE_KEY) if (stored) { const parsed: unknown = JSON.parse(stored) if (!Array.isArray(parsed)) return new Set() return new Set(parsed.filter((c: unknown) => typeof c === 'string' && AI_PERMISSION_CATEGORIES.some(cat => cat.id === c)) as AIContextCategory[]) } } catch (e) { if (import.meta.env.DEV) console.warn('Failed to load AI permissions from storage', e) } return new Set() } function save() { try { localStorage.setItem(STORAGE_KEY, JSON.stringify([...enabled.value])) } catch { /* localStorage full or unavailable */ } } function isEnabled(category: AIContextCategory): boolean { return enabled.value.has(category) } function toggle(category: AIContextCategory) { if (enabled.value.has(category)) { enabled.value.delete(category) } else { enabled.value.add(category) } // Trigger reactivity enabled.value = new Set(enabled.value) save() } function enableAll() { enabled.value = new Set(AI_PERMISSION_CATEGORIES.map(c => c.id)) save() } function disableAll() { enabled.value = new Set() save() } const enabledCategories = computed(() => [...enabled.value]) const allEnabled = computed(() => enabled.value.size === AI_PERMISSION_CATEGORIES.length) const noneEnabled = computed(() => enabled.value.size === 0) return { enabled, isEnabled, toggle, enableAll, disableAll, enabledCategories, allEnabled, noneEnabled, } })