import { useState, useEffect, useCallback } from 'react';
import { api } from '../lib/api';
import { relativeTime } from '../lib/utils';
import Card from '../components/Card';
import Badge from '../components/Badge';
// Channel lookup: tab-name → Redis key prefix used by discord_bot.py
const TABS = ['STM', 'Lifecycle', 'LPM', 'MAGMA', 'Foresight'];
const SHARDS = Array.from({ length: 15 }, (_, i) => ({ id: i, fillPct: 0, vectors: 0 }));
// STM tab: reads live from /memory/stm/:channelId
function STMTab() {
const [channelId, setChannelId] = useState('');
const [inputId, setInputId] = useState('');
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const fetchSTM = useCallback(async (cid) => {
if (!cid) return;
setLoading(true); setError(null);
try { const d = await api.memory.stm(cid); setData(d); }
catch (e) { setError(e.message); }
finally { setLoading(false); }
}, []);
return (
{k} {v} ✗ {error} Loading... CONTEXT WINDOW {data.context_window_count} LIFECYCLE CELLS {data.lifecycle_cell_count} No context. Send a Discord message to populate. Lifecycle Cells {cell.content ?? ''} Enter a Discord channel ID above to view STM.
STM (Redis) → Lifecycle → RAPTOR → Zilliz x15 unified pipeline.
{k}
{v}
lifecycle.py active. Ingests every Discord message + /infer call. MemCells promoted to MemScene after heat threshold (6h TTL). Foresight signal feeds rd_loop.py proposal generation.
{k}
{v}
Shard: hash(user_id) % 15. RAPTOR tree summarises clusters before upsert. Live fill % available after Zilliz stats endpoint added.
{k}
{v}
{name}
{desc}
magma_graph.py active. NetworkX in-memory + Redis persistence. D3 force-directed visualisation available in next phase when graph query endpoint is added. +45.5% reasoning accuracy (arXiv:2601.03236).
{k}
{v}
Foresight predicts what Ghost will need before asking. Drives autonomous R&D proposals visible in Projects tab. Signal strength determined by MemScene heat score over 6h window.