From 6cd91b2f4b6cf428520b69bbd0b847f2fe01d43f Mon Sep 17 00:00:00 2001 From: Aaron Nelson Date: Sun, 26 Apr 2026 21:20:58 -0400 Subject: [PATCH] =?UTF-8?q?Add=20Dreamer=20section=20to=20settings=20?= =?UTF-8?q?=E2=80=94=20Dream=20Now=20button,=20mode=20selector,=20lucid=20?= =?UTF-8?q?task=20input,=20last=20dream=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/SettingsPanel.tsx | 57 +++++++++++++++++++++++++++++++++++- lib/api.ts | 12 ++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/components/SettingsPanel.tsx b/components/SettingsPanel.tsx index e3339ab..a43ad60 100644 --- a/components/SettingsPanel.tsx +++ b/components/SettingsPanel.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from 'react'; import { useStore } from '@/lib/store'; import { api, auth } from '@/lib/api'; -import type { Status } from '@/lib/api'; +import type { Status, DreamerStatus } from '@/lib/api'; export default function SettingsPanel() { const { settingsOpen, setSettingsOpen, settings, setSettings } = useStore(); @@ -11,10 +11,16 @@ export default function SettingsPanel() { const [memory, setMemory] = useState(''); const [editingMemory, setEditingMemory] = useState(false); const [reindexing, setReindexing] = useState(false); + const [dreamerStatus, setDreamerStatus] = useState(null); + const [dreamMode, setDreamMode] = useState('nrem'); + const [dreamTask, setDreamTask] = useState(''); + const [dreaming, setDreaming] = useState(false); + const [dreamStarted, setDreamStarted] = useState(false); useEffect(() => { if (!settingsOpen) return; api.getStatus().then(setStatus).catch(console.error); + api.getDreamerStatus().then(setDreamerStatus).catch(console.error); api.getMemory().then(d => setMemory(d.content)).catch(console.error); }, [settingsOpen]); @@ -29,6 +35,18 @@ export default function SettingsPanel() { setEditingMemory(false); } + async function triggerDream() { + setDreaming(true); + setDreamStarted(false); + const result = await api.runDreamer(dreamMode, dreamTask || undefined); + setDreaming(false); + if (result.started) { + setDreamStarted(true); + setTimeout(() => setDreamStarted(false), 4000); + setTimeout(() => api.getDreamerStatus().then(setDreamerStatus), 5000); + } + } + async function triggerReindex() { setReindexing(true); await api.reindex(); @@ -188,6 +206,43 @@ export default function SettingsPanel() { + {/* Dreamer */} +
+
+ + +
+ + + + {dreamMode === 'lucid' && ( +
+ setDreamTask(e.target.value)} + placeholder="What question should the dreamer pursue?" + className="w-full rounded-md px-3 py-2 text-xs" + style={{ background: 'var(--bg3)', border: '1px solid var(--border2)', color: 'var(--text)', fontFamily: 'var(--font-sans)' }} + /> +
+ )} + + + {dreaming ? 'Starting...' : dreamStarted ? 'Started ✓' : 'Dream'} + + +
+ {/* System */}
diff --git a/lib/api.ts b/lib/api.ts index 0227c8f..a464e83 100644 --- a/lib/api.ts +++ b/lib/api.ts @@ -32,6 +32,12 @@ export const api = { request<{ saved: boolean }>('/memory', { method: 'POST', body: JSON.stringify({ content }) }), getStatus: () => request('/status'), reindex: () => request<{ started: boolean }>('/reindex', { method: 'POST' }), + getDreamerStatus: () => request('/dreamer/status'), + runDreamer: (mode: string, task?: string) => + request<{ started: boolean; mode: string }>('/dreamer/run', { + method: 'POST', + body: JSON.stringify({ mode, task }), + }), transcribe: async (audio: Blob): Promise<{ text: string }> => { const form = new FormData(); form.append('audio', audio, 'recording.webm'); @@ -86,6 +92,12 @@ export interface ChatResponse { sources: string[]; conversation_id: string; } +export interface DreamerStatus { + last_dream: string; + last_mode: string; + last_file: string; +} + export interface Status { aaron_ai: string; watcher: string;