/ src / lib / server / memory / dream-cycles.ts
dream-cycles.ts
 1  import fs from 'fs'
 2  import path from 'path'
 3  import { DATA_DIR } from '@/lib/server/data-dir'
 4  import { hmrSingleton, safeJsonParse } from '@/lib/shared-utils'
 5  import type { DreamCycle } from '@/types'
 6  
 7  const DREAM_CYCLES_PATH = path.join(DATA_DIR, 'dream-cycles.json')
 8  
 9  const state = hmrSingleton('__dream_cycles__', () => ({
10    cycles: null as DreamCycle[] | null,
11  }))
12  
13  function ensureLoaded(): DreamCycle[] {
14    if (state.cycles !== null) return state.cycles
15    try {
16      const raw = fs.readFileSync(DREAM_CYCLES_PATH, { encoding: 'utf-8' })
17      state.cycles = safeJsonParse<DreamCycle[]>(raw, [])
18    } catch {
19      state.cycles = []
20    }
21    return state.cycles
22  }
23  
24  function persist(): void {
25    fs.mkdirSync(path.dirname(DREAM_CYCLES_PATH), { recursive: true })
26    fs.writeFileSync(DREAM_CYCLES_PATH, JSON.stringify(ensureLoaded(), null, 2), { encoding: 'utf-8' })
27  }
28  
29  export function saveDreamCycle(cycle: DreamCycle): void {
30    const cycles = ensureLoaded()
31    const idx = cycles.findIndex((c) => c.id === cycle.id)
32    if (idx >= 0) {
33      cycles[idx] = cycle
34    } else {
35      cycles.push(cycle)
36    }
37    persist()
38  }
39  
40  export function listDreamCycles(agentId?: string, limit = 50): DreamCycle[] {
41    const cycles = ensureLoaded()
42    const filtered = agentId ? cycles.filter((c) => c.agentId === agentId) : [...cycles]
43    filtered.sort((a, b) => b.startedAt - a.startedAt)
44    return filtered.slice(0, limit)
45  }
46  
47  export function getDreamCycle(id: string): DreamCycle | null {
48    return ensureLoaded().find((c) => c.id === id) ?? null
49  }