import { writable, derived, get } from 'svelte/store'; export interface PromptMode { id: string; name: string; instruction: string; emoji: string; color: string; isGlobal: boolean; enabled: boolean; // For global modes - whether they're currently active hidden?: boolean; // Whether the mode is hidden from the UI } export interface PromptItem { id: string; text: string; status: 'pending' | 'active' | 'completed'; createdAt: Date; modeIds?: string[]; // IDs of modes applied to this specific prompt targetTerminalId?: string; // Panel ID of target terminal (undefined = auto-select AI CLI) } interface PromptQueueState { items: PromptItem[]; isRunning: boolean; currentPromptId: string | null; modes: PromptMode[]; // All available modes (global and custom) } // Default modes const DEFAULT_MODES: PromptMode[] = [ { id: 'brutal-honesty', name: 'Brutal Honesty', instruction: 'Be brutally honest.', emoji: '💯', color: '#ff6b6b', isGlobal: true, enabled: false }, { id: 'brainstorm', name: 'Brainstorm', instruction: 'Be extra creative as if in a brainstorming session.', emoji: '💡', color: '#4ecdc4', isGlobal: true, enabled: false } ]; function createPromptQueueStore() { const { subscribe, set, update } = writable({ items: [], isRunning: false, currentPromptId: null, modes: [...DEFAULT_MODES] }); // Load from localStorage on initialization if (typeof window !== 'undefined') { const saved = localStorage.getItem('morphbox-prompt-queue'); if (saved) { try { const parsed = JSON.parse(saved); set({ items: parsed.items?.map((item: any) => ({ ...item, createdAt: new Date(item.createdAt) })) || [], isRunning: false, // Always start stopped currentPromptId: null, modes: parsed.modes || [...DEFAULT_MODES] }); } catch (e) { console.error('Failed to load prompt queue:', e); } } } // Save to localStorage on changes subscribe(state => { if (typeof window !== 'undefined') { localStorage.setItem('morphbox-prompt-queue', JSON.stringify({ items: state.items.map(item => ({ ...item, createdAt: item.createdAt.toISOString() })), modes: state.modes })); } }); return { subscribe, addPrompt(text: string, targetTerminalId?: string) { if (!text.trim()) return; update(state => ({ ...state, items: [...state.items, { id: `prompt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, text: text.trim(), status: 'pending', createdAt: new Date(), targetTerminalId }] })); }, removePrompt(id: string) { update(state => ({ ...state, items: state.items.filter(item => item.id !== id), currentPromptId: state.currentPromptId === id ? null : state.currentPromptId })); }, updatePrompt(id: string, text: string) { update(state => ({ ...state, items: state.items.map(item => item.id === id ? { ...item, text: text.trim() } : item ) })); }, setPromptStatus(id: string, status: PromptItem['status']) { update(state => ({ ...state, items: state.items.map(item => item.id === id ? { ...item, status } : item ), currentPromptId: status === 'active' ? id : (state.currentPromptId === id ? null : state.currentPromptId) })); }, setTargetTerminal(id: string, terminalId: string | undefined) { update(state => ({ ...state, items: state.items.map(item => item.id === id ? { ...item, targetTerminalId: terminalId } : item ) })); }, start() { update(state => ({ ...state, isRunning: true })); }, stop() { update(state => ({ ...state, isRunning: false, currentPromptId: null, items: state.items.map(item => ({ ...item, // Reset active prompts to pending so they can be re-run if needed // Keep completed prompts as-is so user can see what was done status: item.status === 'active' ? 'pending' : item.status })) })); }, getNextPending(): PromptItem | null { const state = get({ subscribe }); return state.items.find(item => item.status === 'pending') || null; }, removeCompleted() { update(state => ({ ...state, items: state.items.filter(item => item.status !== 'completed') })); }, clear() { set({ items: [], isRunning: false, currentPromptId: null }); }, reorderItems(fromIndex: number, toIndex: number) { update(state => { const items = [...state.items]; const [movedItem] = items.splice(fromIndex, 1); items.splice(toIndex, 0, movedItem); return { ...state, items }; }); }, // Mode management methods addMode(mode: Omit) { update(state => ({ ...state, modes: [...state.modes, { ...mode, id: `mode-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` }] })); }, updateMode(id: string, updates: Partial) { update(state => ({ ...state, modes: state.modes.map(mode => mode.id === id ? { ...mode, ...updates } : mode ) })); }, deleteMode(id: string) { update(state => ({ ...state, modes: state.modes.filter(mode => mode.id !== id), // Remove this mode from all prompts items: state.items.map(item => ({ ...item, modeIds: item.modeIds?.filter(modeId => modeId !== id) })) })); }, toggleGlobalMode(id: string) { update(state => ({ ...state, modes: state.modes.map(mode => mode.id === id ? { ...mode, enabled: !mode.enabled } : mode ) })); }, togglePromptMode(promptId: string, modeId: string) { update(state => ({ ...state, items: state.items.map(item => { if (item.id !== promptId) return item; const modeIds = item.modeIds || []; const hasMode = modeIds.includes(modeId); return { ...item, modeIds: hasMode ? modeIds.filter(id => id !== modeId) : [...modeIds, modeId] }; }) })); }, toggleModeVisibility(id: string) { update(state => ({ ...state, modes: state.modes.map(mode => mode.id === id ? { ...mode, hidden: !mode.hidden } : mode ) })); } }; } export const promptQueueStore = createPromptQueueStore(); // Derived store for pending prompts count export const pendingPromptsCount = derived( promptQueueStore, $store => $store.items.filter(item => item.status === 'pending').length ); // Derived store for active prompt export const activePrompt = derived( promptQueueStore, $store => $store.items.find(item => item.status === 'active') || null );