Add Dreamer section to settings — Dream Now button, mode selector, lucid task input, last dream status
This commit is contained in:
@@ -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<DreamerStatus | null>(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() {
|
||||
</Row>
|
||||
</Section>
|
||||
|
||||
{/* Dreamer */}
|
||||
<Section title="Dreamer">
|
||||
<div className="grid grid-cols-2 gap-2 mb-3">
|
||||
<StatCard number={dreamerStatus?.last_mode?.toUpperCase() || '—'} label="last mode" />
|
||||
<StatCard number={dreamerStatus?.last_dream || '—'} label="last dream" />
|
||||
</div>
|
||||
<Row label="Mode">
|
||||
<select
|
||||
value={dreamMode}
|
||||
onChange={e => setDreamMode(e.target.value)}
|
||||
className="rounded-md px-2 py-1 text-sm"
|
||||
style={{ background: 'var(--bg3)', border: '1px solid var(--border2)', color: 'var(--text)', fontFamily: 'var(--font-sans)' }}
|
||||
>
|
||||
<option value="nrem">NREM — consolidation</option>
|
||||
<option value="early-rem">Early REM — personal</option>
|
||||
<option value="late-rem">Late REM — associative</option>
|
||||
<option value="lucid">Lucid — targeted</option>
|
||||
</select>
|
||||
</Row>
|
||||
{dreamMode === 'lucid' && (
|
||||
<div className="py-2" style={{ borderBottom: '1px solid var(--border)' }}>
|
||||
<input
|
||||
value={dreamTask}
|
||||
onChange={e => 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)' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Row label="Dream now" desc={dreamStarted ? 'Dream started — check Journal/Dreams/' : 'Run the dreamer immediately'}>
|
||||
<SBtn primary onClick={triggerDream} disabled={dreaming || (dreamMode === 'lucid' && !dreamTask.trim())}>
|
||||
{dreaming ? 'Starting...' : dreamStarted ? 'Started ✓' : 'Dream'}
|
||||
</SBtn>
|
||||
</Row>
|
||||
</Section>
|
||||
|
||||
{/* System */}
|
||||
<Section title="System">
|
||||
<StatusRow label="Aaron AI service" value={status?.aaron_ai || 'unknown'} ok={status?.aaron_ai === 'running'} />
|
||||
|
||||
+12
@@ -32,6 +32,12 @@ export const api = {
|
||||
request<{ saved: boolean }>('/memory', { method: 'POST', body: JSON.stringify({ content }) }),
|
||||
getStatus: () => request<Status>('/status'),
|
||||
reindex: () => request<{ started: boolean }>('/reindex', { method: 'POST' }),
|
||||
getDreamerStatus: () => request<DreamerStatus>('/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;
|
||||
|
||||
Reference in New Issue
Block a user