Let the console search, browse, forget and mount

The store had a write path, a mount path and a search path, and the console
still showed a dashboard of counters. Nothing in the UI could ask what someone
knows, page through atoms, look at a wordless picture, forget one memory, or
mount a cartridge — so the mechanisms built in P0 were invisible.

Backend:
- senses.py: one function decides what this machine can perceive. /api/status
  and doctor each computed it before, which is two truths. Picture atoms are now
  counted by image_ref rather than by modality, so a screenshot crop from a PDF
  counts and a picture whose bytes were deleted stops claiming it can be encoded.
- browse.py: GET /api/atoms pages newest-first through v_atoms_current with
  modality/holder/source filters; GET /api/atoms/{id}/image serves the stored
  bytes so a picture with no OCR text can be looked at.
- Deleted 8 HTTP routes nobody calls (4 benchmark, research modules, dense index,
  visual-contradiction-proof, memory-map). Their functions stay: the CLI and the
  proof checks use them. The surface is 30 routes, pinned as a set by a test so a
  new unused route fails the suite.

Frontend: App.tsx (517 lines) became a 131-line shell plus seven panels that own
their own fetches, and lib/format.ts. types.ts now carries the memory dimensions
the backend has been sending since schema v2.

Two invented fields were rendering lies: AdapterPanel showed gpu_available and
probe_status, which AdapterLoadReport does not have — every machine looked GPU-less
including this one. The panel now shows only what the server says.

Proof: scripts/ui_smoke.sh starts the API on a fresh temp home, serves the built
UI from the same origin, and drives five interactions in a real browser — search
as somebody in a scenario, page and view a wordless picture, forget, mount, read
adapter states with reasons. It prints the mount refusal verbatim rather than
pretending the mount succeeded.

Gates: 263 pytest passed; ruff and mypy clean on the 8 touched backend files
(repo-wide mypy unchanged at 24 errors / 6 files); pyright 0 errors there;
go build/vet/test/gofmt clean; npm build + eslint clean; ui_smoke and
mcp_write_smoke both PASS.
This commit is contained in:
ZacharyZhang-NY committed 2026-10-08 05:13:38 -04:00
1 parent a5008e1476
commit 9f91ff7ed7
27 files changed
+2146 -616

No files matched your search

+63 -449
View File
@@ -1,96 +1,37 @@
import {
Activity,
Archive,
Braces,
CheckCircle,
Cpu,
Database,
FileSearch,
Gauge,
GitBranch,
Image as ImageIcon,
Play,
RefreshCw,
Send,
Server,
ShieldCheck,
Upload,
} from 'lucide-react';
import { FormEvent, ReactNode, useEffect, useMemo, useState } from 'react';
import {
askQuestion,
getAdapters,
getLatestProofSuite,
getMemoryMap,
getStatus,
ingestPath,
runHashHop,
runProofSuite,
uploadFiles,
} from './api';
import type {
AdapterStatus,
AnswerResponse,
HashHopProof,
IngestResponse,
MemoryMap,
ProofSuiteReport,
RuntimeProfile,
SystemStatus,
} from './types';
import { Activity, Archive, Database, Gauge, RefreshCw, Server } from 'lucide-react';
import { useEffect, useState } from 'react';
const profiles: Array<{ id: RuntimeProfile; label: string }> = [
{ id: 'live_demo', label: 'Live Demo' },
{ id: 'extreme_context', label: 'Extreme' },
{ id: 'library_100m', label: '100M Library' },
{ id: 'research_theater', label: 'Research' },
];
import { getAdapters, getStatus } from './api';
import { AdapterPanel } from './components/AdapterPanel';
import { CartridgePanel } from './components/CartridgePanel';
import { CompilerPanel } from './components/CompilerPanel';
import { IngestPanel } from './components/IngestPanel';
import { MemoryPanel } from './components/MemoryPanel';
import { ProofPanel } from './components/ProofPanel';
import { SensesPanel } from './components/SensesPanel';
import { Kpi, Panel, Quiet } from './components/ui';
import { errorMessage, formatBytes, formatNumber, formatRuntimeDetail, formatVram } from './lib/format';
import type { AdapterStatus, CacheLayerStatus, SystemStatus } from './types';
export function App() {
const [status, setStatus] = useState<SystemStatus | null>(null);
const [memoryMap, setMemoryMap] = useState<MemoryMap | null>(null);
const [adapters, setAdapters] = useState<AdapterStatus[]>([]);
const [profile, setProfile] = useState<RuntimeProfile>('library_100m');
const [path, setPath] = useState('');
const [cartridgeName, setCartridgeName] = useState('ely-eye-cartridge');
const [files, setFiles] = useState<File[]>([]);
const [question, setQuestion] = useState('');
const [answer, setAnswer] = useState<AnswerResponse | null>(null);
const [hashHop, setHashHop] = useState<HashHopProof | null>(null);
const [proofSuite, setProofSuite] = useState<ProofSuiteReport | null>(null);
const [lastIngest, setLastIngest] = useState<IngestResponse | null>(null);
const [busy, setBusy] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const refresh = async () => {
setError(null);
const [nextStatus, nextMap, nextAdapters, nextProofSuite] = await Promise.all([
getStatus(),
getMemoryMap(),
getAdapters(),
getLatestProofSuite().catch(() => null),
]);
async function refresh() {
const [nextStatus, nextAdapters] = await Promise.all([getStatus(), getAdapters()]);
setStatus(nextStatus);
setMemoryMap(nextMap);
setAdapters(nextAdapters);
setProofSuite(nextProofSuite);
};
}
useEffect(() => {
let cancelled = false;
async function loadInitial() {
try {
const [nextStatus, nextMap, nextAdapters, nextProofSuite] = await Promise.all([
getStatus(),
getMemoryMap(),
getAdapters(),
getLatestProofSuite().catch(() => null),
]);
const [nextStatus, nextAdapters] = await Promise.all([getStatus(), getAdapters()]);
if (!cancelled) {
setStatus(nextStatus);
setMemoryMap(nextMap);
setAdapters(nextAdapters);
setProofSuite(nextProofSuite);
}
} catch (err) {
if (!cancelled) {
@@ -104,86 +45,16 @@ export function App() {
};
}, []);
const memoryLayers = useMemo(() => status?.memory.layers ?? [], [status]);
const boundAdapters = useMemo(() => adapters.filter((adapter) => adapter.cartridge_bound).length, [adapters]);
const passedProofChecks = useMemo(
() => proofSuite?.checks.filter((check) => check.status === 'passed').length ?? 0,
[proofSuite],
);
async function submitPath(event: FormEvent) {
event.preventDefault();
setBusy('ingest-path');
setError(null);
async function refreshQuietly() {
try {
const result = await ingestPath(path, cartridgeName);
setLastIngest(result);
await refresh();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitUpload(event: FormEvent) {
event.preventDefault();
setBusy('upload');
setError(null);
try {
const result = await uploadFiles(files, cartridgeName);
setLastIngest(result);
await refresh();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitQuestion(event: FormEvent) {
event.preventDefault();
setBusy('chat');
setError(null);
try {
const result = await askQuestion(question, profile);
setAnswer(result);
await refresh();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitHashHop(kind: 'text' | 'visual') {
setBusy(`hashhop-${kind}`);
setError(null);
try {
const result = await runHashHop(kind, kind === 'visual' ? 2 : 2, kind === 'visual' ? 262144 : 1010000);
setHashHop(result);
await refresh();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitProofSuite() {
setBusy('proof-suite');
setError(null);
try {
const cartridgeId = memoryMap?.cartridges[0]?.cartridge_id;
const result = await runProofSuite(cartridgeId);
setProofSuite(result);
await refresh();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
const layers: CacheLayerStatus[] = status?.memory.layers ?? [];
const boundAdapters = adapters.filter((adapter) => adapter.cartridge_bound).length;
return (
<main className="app-shell">
@@ -192,7 +63,11 @@ export function App() {
<p className="eyebrow">Ely-Eye v4.0</p>
<h1>Local VLM Context OS</h1>
</div>
<button className="icon-button" title="Refresh status" onClick={() => refresh().catch((err) => setError(errorMessage(err)))}>
<button
className="icon-button"
title="Refresh status"
onClick={() => refreshQuietly()}
>
<RefreshCw size={18} />
</button>
</header>
@@ -200,318 +75,57 @@ export function App() {
{error && <div className="error-line">{error}</div>}
<section className="kpi-grid" aria-label="system status">
<Kpi icon={<Server size={18} />} label="Runtime" value={status?.runtime.available ? 'ready' : 'offline'} detail={formatRuntimeDetail(status)} />
<Kpi icon={<Gauge size={18} />} label="GPU" value={status?.runtime.gpu_name ?? 'unknown'} detail={formatVram(status)} />
<Kpi icon={<Database size={18} />} label="Library" value={formatNumber(status?.memory.library_token_equivalent ?? 0)} detail="token eq" />
<Kpi icon={<Archive size={18} />} label="Cartridges" value={String(status?.memory.cartridges ?? 0)} detail={`${boundAdapters} adapters bound`} />
<Kpi
icon={<Server size={18} />}
label="Runtime"
value={status?.runtime.available ? 'ready' : 'offline'}
detail={formatRuntimeDetail(status)}
/>
<Kpi
icon={<Gauge size={18} />}
label="GPU"
value={status?.runtime.gpu_name ?? 'unknown'}
detail={formatVram(status)}
/>
<Kpi
icon={<Database size={18} />}
label="Library"
value={formatNumber(status?.memory.library_token_equivalent ?? 0)}
detail={`${formatNumber(status?.memory.active_token_equivalent ?? 0)} token eq open`}
/>
<Kpi
icon={<Archive size={18} />}
label="Cartridges"
value={String(status?.memory.cartridges ?? 0)}
detail={`${boundAdapters} adapters bound`}
/>
</section>
<section className="workspace-grid">
<Panel title="Input Stream" icon={<Upload size={17} />}>
<form className="stack" onSubmit={submitPath}>
<label>
Cartridge
<input value={cartridgeName} onChange={(event) => setCartridgeName(event.target.value)} />
</label>
<label>
Local path
<input value={path} onChange={(event) => setPath(event.target.value)} />
</label>
<button className="action-button" disabled={!path || busy === 'ingest-path'}>
<FileSearch size={16} />
Ingest Path
</button>
</form>
<form className="stack" onSubmit={submitUpload}>
<label>
Files
<input type="file" multiple onChange={(event) => setFiles(Array.from(event.target.files ?? []))} />
</label>
<button className="action-button secondary" disabled={files.length === 0 || busy === 'upload'}>
<Upload size={16} />
Upload Files
</button>
</form>
{lastIngest && (
<div className="metric-strip">
<span>{lastIngest.source_count} sources</span>
<span>{lastIngest.atom_count} atoms</span>
<span>{formatNumber(lastIngest.token_equivalent)} tokens</span>
</div>
)}
</Panel>
<Panel title="Context Compiler" icon={<Braces size={17} />}>
<div className="segments">
{profiles.map((item) => (
<button
key={item.id}
className={profile === item.id ? 'segment active' : 'segment'}
onClick={() => setProfile(item.id)}
type="button"
>
{item.label}
</button>
))}
</div>
<form className="stack" onSubmit={submitQuestion}>
<textarea value={question} onChange={(event) => setQuestion(event.target.value)} rows={6} />
<button className="action-button" disabled={!question || busy === 'chat'}>
<Send size={16} />
Ask
</button>
</form>
{answer && (
<div className="answer-box">
<p>{answer.answer}</p>
<div className="metric-strip">
<span>{answer.context.hits.length} hits</span>
<span>{Math.round(answer.verifier.citation_accuracy * 100)}% citations</span>
<span>{answer.runtime_backend}</span>
</div>
</div>
)}
</Panel>
<Panel title="Memory OS" icon={<Database size={17} />}>
<div className="layer-list">
{memoryLayers.map((layer) => (
<div className="layer-row" key={layer.layer}>
<span>{layer.layer}</span>
<strong>{layer.entries}</strong>
<small>{layer.hit_count} hit / {layer.miss_count} miss</small>
</div>
))}
{memoryLayers.length === 0 && <div className="quiet-line">No cache events</div>}
</div>
<div className="atom-list">
{(memoryMap?.atoms ?? []).slice(0, 8).map((atom) => (
<div className="atom-row" key={atom.atom_id}>
<span>{atom.modality}</span>
<strong>{atom.atom_id}</strong>
<small>{atom.source}</small>
</div>
))}
</div>
</Panel>
<Panel title="Adapter Matrix" icon={<Cpu size={17} />}>
<div className="adapter-list">
{adapters.map((adapter) => (
<div className="adapter-row" key={adapter.adapter_id}>
<header>
<span>{adapter.kind.replaceAll('_', '-')}</span>
{adapter.cartridge_bound && <CheckCircle size={16} aria-label="bound" />}
</header>
<strong>{adapter.base_model}</strong>
<div className="adapter-metrics">
<small>{adapter.training_method}</small>
<small>{adapter.precision}</small>
<small title={adapter.unsloth_model_type ?? adapter.framework}>{formatFramework(adapter.framework)}</small>
<small title={adapter.optimizer_family ?? adapter.optimizer ?? undefined}>{formatOptimizer(adapter)}</small>
<small title={adapter.gradient_checkpointing_mode ?? undefined}>{formatCheckpointing(adapter)}</small>
<small title={adapter.triton_version ?? undefined}>{adapter.triton_version ? `triton ${adapter.triton_version}` : 'triton pending'}</small>
<small>{formatBytes(adapter.weight_bytes)}</small>
<small>{formatNumber(adapter.trainable_params)} params</small>
<small>{adapter.final_loss?.toFixed(3) ?? 'loss pending'}</small>
<small>{adapter.training_trace_steps}/{adapter.max_steps} trace</small>
<small>{formatNumber(adapter.optimizer_update_count)} updates</small>
<small>{adapter.loss_delta == null ? 'loss delta pending' : `loss delta ${adapter.loss_delta.toFixed(3)}`}</small>
<small>{adapter.bf16 ? 'cuda bf16' : 'precision pending'}</small>
<small>{formatNumber(adapter.adapter_lora_tensor_count)} LoRA tensors</small>
<small>{formatNumber(adapter.adapter_nonzero_elements)} nonzero</small>
<small>{adapter.adapter_weights_finite ? 'finite weights' : 'weights pending'}</small>
<small>{adapter.adapter_weight_sha256 ? `sha ${shortHash(adapter.adapter_weight_sha256)}` : 'sha pending'}</small>
<small>{formatDuration(adapter.training_wall_seconds)}</small>
</div>
</div>
))}
{adapters.length === 0 && <div className="quiet-line">No adapters found</div>}
</div>
</Panel>
<Panel title="PRD Proof Suite" icon={<ShieldCheck size={17} />}>
<div className="proof-suite-header">
<button className="action-button secondary" onClick={submitProofSuite} disabled={busy === 'proof-suite'}>
<Play size={16} />
Run Suite
</button>
<div className={proofSuite?.status === 'passed' ? 'proof-pill passed' : 'proof-pill'}>
{proofSuite ? `${passedProofChecks}/${proofSuite.checks.length} passed` : 'pending'}
</div>
</div>
{proofSuite && (
<div className="proof-list">
{proofSuite.checks.map((check) => (
<article className="proof-row" key={check.name}>
<header>
<strong>{check.name}</strong>
<span className={check.status === 'passed' ? 'proof-status passed' : 'proof-status'}>
{check.status}
</span>
</header>
<p>{check.detail}</p>
<small>{check.evidence[0]}</small>
</article>
))}
<div className="proof-box">
<strong>{proofSuite.proof_id}</strong>
<span>{proofSuite.status}</span>
<small>{proofSuite.cartridge_id}</small>
<small>{proofSuite.dna_after ?? proofSuite.dna_before}</small>
</div>
</div>
)}
{!proofSuite && <div className="quiet-line">Proof suite has not run yet</div>}
</Panel>
<Panel title="Evidence Viewer" icon={<ImageIcon size={17} />}>
<div className="evidence-list">
{(answer?.context.hits ?? []).slice(0, 8).map((hit) => (
<article key={hit.atom.atom_id} className="evidence-row">
<header>
<span>{hit.atom.modality}</span>
<strong>{hit.final_score.toFixed(3)}</strong>
</header>
<p>{hit.atom.text.slice(0, 280)}</p>
<small>{hit.atom.source}</small>
</article>
))}
{!answer && <div className="quiet-line">Evidence appears after a compiled answer</div>}
</div>
</Panel>
<Panel title="Visual HashHop Arena" icon={<GitBranch size={17} />}>
<div className="button-row">
<button className="action-button secondary" onClick={() => submitHashHop('visual')} disabled={busy === 'hashhop-visual'}>
<Play size={16} />
Visual 2-hop
</button>
<button className="action-button secondary" onClick={() => submitHashHop('text')} disabled={busy === 'hashhop-text'}>
<Play size={16} />
Text 2-hop
</button>
</div>
{hashHop && (
<div className="proof-box">
<strong>{hashHop.proof_id}</strong>
<span>{hashHop.kind}</span>
<span>{hashHop.hops} hops</span>
<span>{formatNumber(hashHop.token_equivalent)} token eq</span>
<small>{hashHop.expected_target_id}</small>
</div>
)}
</Panel>
<MemoryPanel onChanged={refreshQuietly} />
<CartridgePanel onChanged={refreshQuietly} />
<CompilerPanel onChanged={refreshQuietly} />
<IngestPanel onChanged={refreshQuietly} />
<SensesPanel senses={status?.senses ?? null} />
<Panel title="Cache Trace" icon={<Activity size={17} />}>
<div className="trace-list">
{memoryLayers.map((layer) => (
{layers.map((layer) => (
<div key={layer.layer} className="trace-row">
<span>{layer.layer}</span>
<meter min={0} max={Math.max(1, layer.hit_count + layer.miss_count)} value={layer.hit_count} />
<meter
min={0}
max={Math.max(1, layer.hit_count + layer.miss_count)}
value={layer.hit_count}
/>
<small>{formatBytes(layer.bytes_estimate)}</small>
</div>
))}
{memoryLayers.length === 0 && <div className="quiet-line">Waiting for retrieval</div>}
{layers.length === 0 && <Quiet>Waiting for retrieval</Quiet>}
</div>
</Panel>
<AdapterPanel adapters={adapters} />
<ProofPanel />
</section>
</main>
);
}
function Panel({ title, icon, children }: { title: string; icon: ReactNode; children: ReactNode }) {
return (
<section className="panel">
<header className="panel-header">
<span className="panel-icon">{icon}</span>
<h2>{title}</h2>
</header>
{children}
</section>
);
}
function Kpi({ icon, label, value, detail }: { icon: ReactNode; label: string; value: string; detail: string }) {
return (
<section className="kpi">
<span className="panel-icon">{icon}</span>
<div>
<p>{label}</p>
<strong>{value}</strong>
<small>{detail}</small>
</div>
</section>
);
}
function errorMessage(err: unknown): string {
if (err instanceof Error) {
return err.message;
}
return String(err);
}
function formatNumber(value: number): string {
return new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1 }).format(value);
}
function formatBytes(value: number): string {
if (value < 1024) {
return `${value} B`;
}
if (value < 1024 * 1024) {
return `${(value / 1024).toFixed(1)} KiB`;
}
return `${(value / 1024 / 1024).toFixed(1)} MiB`;
}
function formatDuration(value: number | null): string {
if (typeof value !== 'number') {
return 'time pending';
}
if (value < 60) {
return `${value.toFixed(1)}s`;
}
return `${Math.round(value / 60)}m`;
}
function shortHash(value: string): string {
return value.slice(0, 8);
}
function formatOptimizer(adapter: AdapterStatus): string {
if (adapter.optimizer === 'paged_adamw_8bit') {
return 'paged 8-bit AdamW';
}
return adapter.optimizer_family ?? adapter.optimizer ?? 'optimizer pending';
}
function formatFramework(value: string): string {
if (value === 'unsloth_patched_transformers_peft') {
return 'Unsloth patch + PEFT';
}
return value;
}
function formatCheckpointing(adapter: AdapterStatus): string {
if (adapter.gradient_checkpointing_mode === 'unsloth') {
return 'ckpt unsloth';
}
return adapter.gradient_checkpointing ? 'ckpt on' : 'ckpt pending';
}
function formatRuntimeDetail(status: SystemStatus | null): string {
const model = status?.runtime.model_id ?? 'Qwen/Qwen3.5-9B';
const adapter = status?.runtime.adapter_kind?.replaceAll('_', '-');
return adapter ? `${model} · ${adapter}` : model;
}
function formatVram(status: SystemStatus | null): string {
const total = status?.runtime.vram_total_mb;
const used = status?.runtime.vram_used_mb;
if (typeof total === 'number' && typeof used === 'number') {
return `${used} / ${total} MiB`;
}
return status?.runtime.cuda ?? 'CUDA';
}
+84 -5
View File
@@ -1,11 +1,18 @@
import type {
AdapterLoadReport,
AdapterStatus,
AnswerResponse,
AtomPage,
CartridgeManifest,
ForgetReport,
HashHopProof,
IngestResponse,
MemoryMap,
MountState,
ProofSuiteReport,
RuntimeProfile,
RuntimeProfileReport,
SearchFilters,
SearchResult,
SystemStatus,
} from './types';
@@ -22,14 +29,18 @@ export function getStatus(): Promise<SystemStatus> {
return request<SystemStatus>('/api/status');
}
export function getMemoryMap(): Promise<MemoryMap> {
return request<MemoryMap>('/api/memory-map');
}
export function getAdapters(): Promise<AdapterStatus[]> {
return request<AdapterStatus[]>('/api/adapters');
}
export function getRuntimeAdapters(): Promise<AdapterLoadReport> {
return request<AdapterLoadReport>('/api/runtime/adapters');
}
export function getRuntimeProfiles(): Promise<RuntimeProfileReport> {
return request<RuntimeProfileReport>('/api/runtime/profiles');
}
export function ingestPath(path: string, cartridgeName: string): Promise<IngestResponse> {
return request<IngestResponse>('/api/ingest/path', {
method: 'POST',
@@ -61,6 +72,74 @@ export function askQuestion(question: string, profile: RuntimeProfile): Promise<
});
}
export function search(query: string, filters: SearchFilters = {}, topK = 8): Promise<SearchResult> {
const compact: SearchFilters = {};
for (const [key, value] of Object.entries(filters)) {
if (value !== '' && value !== null && value !== undefined) {
compact[key as keyof SearchFilters] = value;
}
}
return request<SearchResult>('/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query, top_k: topK, filters: compact }),
});
}
export function listAtoms(options: { limit?: number; cursor?: string; modality?: string; holder?: string } = {}): Promise<AtomPage> {
const query = new URLSearchParams({ limit: String(options.limit ?? 12) });
if (options.cursor) {
query.set('cursor', options.cursor);
}
if (options.modality) {
query.set('modality', options.modality);
}
if (options.holder) {
query.set('holder', options.holder);
}
return request<AtomPage>(`/api/atoms?${query.toString()}`);
}
export function atomImageUrl(atomId: string): string {
return `/api/atoms/${encodeURIComponent(atomId)}/image`;
}
export function remember(text: string, scenario: string): Promise<unknown> {
return request<unknown>('/api/memory', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text, scenario: scenario || null }),
});
}
export function forget(atomId: string, reason = ''): Promise<ForgetReport> {
return request<ForgetReport>('/api/memory/forget', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ atom_id: atomId, reason }),
});
}
export function listCartridges(): Promise<CartridgeManifest[]> {
return request<CartridgeManifest[]>('/api/cartridges');
}
export function getMounts(): Promise<MountState> {
return request<MountState>('/api/mounts');
}
export function mountCartridge(cartridgeId: string): Promise<CartridgeManifest> {
return request<CartridgeManifest>(`/api/cartridges/${encodeURIComponent(cartridgeId)}/mount`, { method: 'POST' });
}
export function switchCartridge(cartridgeId: string): Promise<CartridgeManifest> {
return request<CartridgeManifest>(`/api/cartridges/${encodeURIComponent(cartridgeId)}/switch`, { method: 'POST' });
}
export function unmountCartridge(cartridgeId: string): Promise<MountState> {
return request<MountState>(`/api/cartridges/${encodeURIComponent(cartridgeId)}/unmount`, { method: 'POST' });
}
export function runHashHop(kind: 'text' | 'visual', hops: number, tokenEquivalent: number): Promise<HashHopProof> {
return request<HashHopProof>('/api/hashhop', {
method: 'POST',
+107
View File
@@ -0,0 +1,107 @@
import { CheckCircle, Cpu } from 'lucide-react';
import { useEffect, useState } from 'react';
import { getRuntimeAdapters } from '../api';
import type { AdapterLoadReport, AdapterStatus } from '../types';
import {
errorMessage,
formatBytes,
formatCheckpointing,
formatDuration,
formatFramework,
formatNumber,
formatOptimizer,
shortHash,
} from '../lib/format';
import { Panel, Quiet } from './ui';
export function AdapterPanel({ adapters }: { adapters: AdapterStatus[] }) {
const [load, setLoad] = useState<AdapterLoadReport | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
async function loadStates() {
try {
const next = await getRuntimeAdapters();
if (!cancelled) {
setLoad(next);
}
} catch (err) {
if (!cancelled) {
setError(errorMessage(err));
}
}
}
void loadStates();
return () => {
cancelled = true;
};
}, []);
return (
<Panel title="Adapter Matrix" icon={<Cpu size={17} />}>
{load && (
<div className="metric-strip">
<span>{load.model_id}</span>
<span>{load.mounted.length} mounted</span>
</div>
)}
<div className="layer-list">
{(load?.adapters ?? []).map((choice) => (
<div className="layer-row" key={choice.kind}>
<span>{choice.kind.replaceAll('_', '-')}</span>
<strong>{choice.state}</strong>
<small title={choice.path ?? undefined}>{choice.reason}</small>
</div>
))}
{!load && <Quiet>Load states unavailable.</Quiet>}
</div>
<div className="adapter-list">
{adapters.map((adapter) => (
<div className="adapter-row" key={adapter.adapter_id}>
<header>
<span>{adapter.kind.replaceAll('_', '-')}</span>
{adapter.cartridge_bound && <CheckCircle size={16} aria-label="bound" />}
</header>
<strong>{adapter.base_model}</strong>
<div className="adapter-metrics">
<small>{adapter.training_method}</small>
<small>{adapter.precision}</small>
<small title={adapter.unsloth_model_type ?? adapter.framework ?? undefined}>
{formatFramework(adapter.framework)}
</small>
<small title={adapter.optimizer_family ?? adapter.optimizer ?? undefined}>
{formatOptimizer(adapter)}
</small>
<small title={adapter.gradient_checkpointing_mode ?? undefined}>{formatCheckpointing(adapter)}</small>
<small title={adapter.triton_version ?? undefined}>
{adapter.triton_version ? `triton ${adapter.triton_version}` : 'triton pending'}
</small>
<small>{formatBytes(adapter.weight_bytes)}</small>
<small>{formatNumber(adapter.trainable_params)} params</small>
<small>{adapter.final_loss?.toFixed(3) ?? 'loss pending'}</small>
<small>
{adapter.training_trace_steps}/{adapter.max_steps} trace
</small>
<small>{formatNumber(adapter.optimizer_update_count)} updates</small>
<small>
{adapter.loss_delta == null ? 'loss delta pending' : `loss delta ${adapter.loss_delta.toFixed(3)}`}
</small>
<small>{adapter.bf16 ? 'cuda bf16' : 'precision pending'}</small>
<small>{formatNumber(adapter.adapter_lora_tensor_count)} LoRA tensors</small>
<small>{formatNumber(adapter.adapter_nonzero_elements)} nonzero</small>
<small>{adapter.adapter_weights_finite ? 'finite weights' : 'weights pending'}</small>
<small>
{adapter.adapter_weight_sha256 ? `sha ${shortHash(adapter.adapter_weight_sha256)}` : 'sha pending'}
</small>
<small>{formatDuration(adapter.training_wall_seconds)}</small>
</div>
</div>
))}
{adapters.length === 0 && <Quiet>No adapters found</Quiet>}
</div>
{error && <div className="error-line">{error}</div>}
</Panel>
);
}
+133
View File
@@ -0,0 +1,133 @@
import { Archive, Play, Square, SwitchCamera } from 'lucide-react';
import { useEffect, useState } from 'react';
import { getMounts, listCartridges, mountCartridge, switchCartridge, unmountCartridge } from '../api';
import type { CartridgeManifest, MountState } from '../types';
import { errorMessage, formatNumber, shortHash } from '../lib/format';
import { Panel, Quiet } from './ui';
export function CartridgePanel({ onChanged }: { onChanged: () => void }) {
const [cartridges, setCartridges] = useState<CartridgeManifest[]>([]);
const [mounts, setMounts] = useState<MountState | null>(null);
const [busy, setBusy] = useState<string | null>(null);
const [notice, setNotice] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
async function load() {
try {
const [nextCartridges, nextMounts] = await Promise.all([listCartridges(), getMounts()]);
setCartridges(nextCartridges);
setMounts(nextMounts);
} catch (err) {
setError(errorMessage(err));
}
}
useEffect(() => {
let cancelled = false;
async function loadInitial() {
try {
const [nextCartridges, nextMounts] = await Promise.all([listCartridges(), getMounts()]);
if (!cancelled) {
setCartridges(nextCartridges);
setMounts(nextMounts);
}
} catch (err) {
if (!cancelled) {
setError(errorMessage(err));
}
}
}
void loadInitial();
return () => {
cancelled = true;
};
}, []);
async function act(cartridgeId: string, verb: 'mount' | 'switch' | 'unmount') {
setBusy(`${verb}-${cartridgeId}`);
setError(null);
try {
if (verb === 'mount') {
await mountCartridge(cartridgeId);
} else if (verb === 'switch') {
await switchCartridge(cartridgeId);
} else {
await unmountCartridge(cartridgeId);
}
setNotice(`${verb} ${cartridgeId}`);
await load();
onChanged();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
return (
<Panel title="Cartridges" icon={<Archive size={17} />}>
<div className="metric-strip">
<span>{mounts?.mounted.length ?? 0} mounted</span>
<span>{mounts?.scoped ? 'search is scoped' : 'search sees the whole store'}</span>
</div>
<div className="adapter-list">
{cartridges.map((cartridge) => {
const mounted = mounts?.mounted.includes(cartridge.cartridge_id) ?? false;
return (
<article className="adapter-row" key={cartridge.cartridge_id}>
<header>
<span>{cartridge.name}</span>
{mounted && <span className="proof-pill passed">mounted</span>}
</header>
<strong>{cartridge.cartridge_id}</strong>
<div className="adapter-metrics">
<small>{formatNumber(cartridge.atom_count)} atoms</small>
<small>{formatNumber(cartridge.source_count)} sources</small>
<small>{formatNumber(cartridge.token_equivalent)} token eq</small>
<small>{cartridge.model_base}</small>
<small title={cartridge.dna ?? undefined}>
{cartridge.dna ? `dna ${shortHash(cartridge.dna)}` : 'dna pending'}
</small>
<small>
{cartridge.kv_fingerprint
? 'kv fingerprint pinned'
: 'no kv fingerprint: mounting must re-check this machine'}
</small>
</div>
<div className="button-row">
<button
className="action-button secondary"
onClick={() => act(cartridge.cartridge_id, 'mount')}
disabled={busy !== null || mounted}
>
<Play size={15} />
Mount
</button>
<button
className="action-button secondary"
onClick={() => act(cartridge.cartridge_id, 'switch')}
disabled={busy !== null}
>
<SwitchCamera size={15} />
Switch
</button>
<button
className="action-button secondary"
onClick={() => act(cartridge.cartridge_id, 'unmount')}
disabled={busy !== null || !mounted}
>
<Square size={15} />
Unmount
</button>
</div>
</article>
);
})}
{cartridges.length === 0 && <Quiet>No cartridge has been finalized yet.</Quiet>}
</div>
{notice && <div className="metric-strip"><span>{notice}</span></div>}
{error && <div className="error-line">{error}</div>}
</Panel>
);
}
+92
View File
@@ -0,0 +1,92 @@
import { Braces, Send } from 'lucide-react';
import { FormEvent, useState } from 'react';
import { askQuestion, atomImageUrl } from '../api';
import type { AnswerResponse, RuntimeProfile } from '../types';
import { errorMessage } from '../lib/format';
import { Panel, Quiet } from './ui';
const PROFILES: Array<{ id: RuntimeProfile; label: string }> = [
{ id: 'live_demo', label: 'Live Demo' },
{ id: 'extreme_context', label: 'Extreme' },
{ id: 'library_100m', label: '100M Library' },
{ id: 'research_theater', label: 'Research' },
];
export function CompilerPanel({ onChanged }: { onChanged: () => void }) {
const [profile, setProfile] = useState<RuntimeProfile>('library_100m');
const [question, setQuestion] = useState('');
const [answer, setAnswer] = useState<AnswerResponse | null>(null);
const [busy, setBusy] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
async function submitQuestion(event: FormEvent) {
event.preventDefault();
if (!question) {
return;
}
setBusy('chat');
setError(null);
try {
setAnswer(await askQuestion(question, profile));
onChanged();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
return (
<Panel title="Context Compiler" icon={<Braces size={17} />}>
<div className="segments">
{PROFILES.map((item) => (
<button
key={item.id}
className={profile === item.id ? 'segment active' : 'segment'}
onClick={() => setProfile(item.id)}
type="button"
>
{item.label}
</button>
))}
</div>
<form className="stack" onSubmit={submitQuestion}>
<textarea value={question} onChange={(event) => setQuestion(event.target.value)} rows={5} />
<button className="action-button" disabled={!question || busy === 'chat'}>
<Send size={16} />
Ask
</button>
</form>
{answer && (
<div className="answer-box">
<p>{answer.answer}</p>
<div className="metric-strip">
<span>{answer.context.hits.length} hits</span>
<span>{Math.round(answer.verifier.citation_accuracy * 100)}% citations</span>
<span>{answer.runtime_backend}</span>
</div>
</div>
)}
<div className="evidence-list">
{(answer?.context.hits ?? []).slice(0, 6).map((hit) => (
<article key={hit.atom.atom_id} className="evidence-row">
<header>
<span>{hit.atom.modality}</span>
<strong>{hit.final_score.toFixed(3)}</strong>
</header>
{hit.atom.image_ref && (
<img className="thumb" src={atomImageUrl(hit.atom.atom_id)} alt={hit.atom.atom_id} loading="lazy" />
)}
<p>{hit.atom.text.slice(0, 240)}</p>
<small>
{hit.atom.source} · {hit.atom.holder_id || 'no holder'}
</small>
</article>
))}
{!answer && <Quiet>Evidence appears after a compiled answer</Quiet>}
</div>
{error && <div className="error-line">{error}</div>}
</Panel>
);
}
+76
View File
@@ -0,0 +1,76 @@
import { FileSearch, Upload } from 'lucide-react';
import { FormEvent, useState } from 'react';
import { ingestPath, uploadFiles } from '../api';
import type { IngestResponse } from '../types';
import { errorMessage, formatNumber } from '../lib/format';
import { Panel } from './ui';
export function IngestPanel({ onChanged }: { onChanged: () => void }) {
const [path, setPath] = useState('');
const [cartridgeName, setCartridgeName] = useState('ely-eye-cartridge');
const [files, setFiles] = useState<File[]>([]);
const [lastIngest, setLastIngest] = useState<IngestResponse | null>(null);
const [busy, setBusy] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
async function run(label: string, work: () => Promise<IngestResponse>) {
setBusy(label);
setError(null);
try {
setLastIngest(await work());
onChanged();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
function submitPath(event: FormEvent) {
event.preventDefault();
void run('ingest-path', () => ingestPath(path, cartridgeName));
}
function submitUpload(event: FormEvent) {
event.preventDefault();
void run('upload', () => uploadFiles(files, cartridgeName));
}
return (
<Panel title="Input Stream" icon={<Upload size={17} />}>
<form className="stack" onSubmit={submitPath}>
<label>
Cartridge
<input value={cartridgeName} onChange={(event) => setCartridgeName(event.target.value)} />
</label>
<label>
Local path
<input value={path} onChange={(event) => setPath(event.target.value)} placeholder="/data/books" />
</label>
<button className="action-button" disabled={!path || busy === 'ingest-path'}>
<FileSearch size={16} />
Ingest Path
</button>
</form>
<form className="stack" onSubmit={submitUpload}>
<label>
Files
<input type="file" multiple onChange={(event) => setFiles(Array.from(event.target.files ?? []))} />
</label>
<button className="action-button secondary" disabled={files.length === 0 || busy === 'upload'}>
<Upload size={16} />
Upload Files
</button>
</form>
{lastIngest && (
<div className="metric-strip">
<span>{lastIngest.source_count} sources</span>
<span>{lastIngest.atom_count} atoms</span>
<span>{formatNumber(lastIngest.token_equivalent)} tokens</span>
</div>
)}
{error && <div className="error-line">{error}</div>}
</Panel>
);
}
+262
View File
@@ -0,0 +1,262 @@
import { ChevronLeft, ChevronRight, Database, Plus, Search, Trash2 } from 'lucide-react';
import { Dispatch, FormEvent, ReactNode, SetStateAction, useEffect, useState } from 'react';
import { atomImageUrl, forget, listAtoms, remember, search } from '../api';
import type { AtomPage, EvidenceAtom, SearchResult } from '../types';
import { errorMessage, formatAgo, formatNumber, formatStamp } from '../lib/format';
import { Panel, Quiet } from './ui';
const MODALITIES = ['text', 'code', 'image', 'audio', 'pdf_page', 'pdf_region', 'video_frame', 'ui_screenshot'];
const PAGE_SIZE = 12;
export function MemoryPanel({ onChanged }: { onChanged: () => void }) {
const [query, setQuery] = useState('');
const [holder, setHolder] = useState('');
const [scenario, setScenario] = useState('');
const [modality, setModality] = useState('');
const [statement, setStatement] = useState('');
const [result, setResult] = useState<SearchResult | null>(null);
const [page, setPage] = useState<AtomPage | null>(null);
const [history, setHistory] = useState<string[]>([]);
const [cursor, setCursor] = useState<string | undefined>(undefined);
const [busy, setBusy] = useState<string | null>(null);
const [notice, setNotice] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
async function loadBrowse(nextCursor?: string) {
try {
const next = await listAtoms({ limit: PAGE_SIZE, cursor: nextCursor, modality, holder });
setPage(next);
} catch (err) {
setError(errorMessage(err));
}
}
useEffect(() => {
let cancelled = false;
async function loadFirstPage() {
try {
const next = await listAtoms({ limit: PAGE_SIZE, modality, holder });
if (!cancelled) {
setPage(next);
}
} catch (err) {
if (!cancelled) {
setError(errorMessage(err));
}
}
}
void loadFirstPage();
return () => {
cancelled = true;
};
}, [modality, holder]);
function changeFilter(apply: Dispatch<SetStateAction<string>>, value: string) {
apply(value);
setHistory([]);
setCursor(undefined);
}
async function submitSearch(event: FormEvent) {
event.preventDefault();
if (!query) {
return;
}
setBusy('search');
setError(null);
setNotice(null);
try {
setResult(await search(query, { holder, scenario, modality }));
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitRemember(event: FormEvent) {
event.preventDefault();
if (!statement) {
return;
}
setBusy('remember');
setError(null);
try {
await remember(statement, scenario);
setNotice(`kept: ${statement.slice(0, 60)}`);
setStatement('');
await loadBrowse();
onChanged();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitForget(atom: EvidenceAtom) {
setBusy(`forget-${atom.atom_id}`);
setError(null);
try {
const report = await forget(atom.atom_id, 'forgotten from the console');
setNotice(
`forgotten: ${report.atoms_deleted} atom${report.atoms_deleted === 1 ? '' : 's'}, ` +
`${report.edges_deleted} links, ${report.cache_entries_cleared} cache entries` +
(report.vector_index_dropped ? ', dense index dropped' : ''),
);
setResult(null);
await loadBrowse();
onChanged();
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
function nextPage() {
if (!page?.next_cursor) {
return;
}
setHistory([...history, cursor ?? '']);
setCursor(page.next_cursor);
void loadBrowse(page.next_cursor);
}
function previousPage() {
if (history.length === 0) {
return;
}
const previous = history[history.length - 1];
setHistory(history.slice(0, -1));
setCursor(previous || undefined);
void loadBrowse(previous || undefined);
}
return (
<Panel title="Memory" icon={<Database size={17} />}>
<form className="stack" onSubmit={submitSearch}>
<label>
Ask what someone knows
<input value={query} onChange={(event) => setQuery(event.target.value)} placeholder="where are the keys" />
</label>
<div className="filter-row">
<label>
Holder
<input
value={holder}
onChange={(event) => changeFilter(setHolder, event.target.value)}
placeholder="any"
/>
</label>
<label>
Scenario
<input value={scenario} onChange={(event) => setScenario(event.target.value)} placeholder="any" />
</label>
<label>
Modality
<select value={modality} onChange={(event) => changeFilter(setModality, event.target.value)}>
<option value="">any</option>
{MODALITIES.map((name) => (
<option key={name} value={name}>
{name}
</option>
))}
</select>
</label>
</div>
<button className="action-button" disabled={!query || busy === 'search'}>
<Search size={16} />
Search
</button>
</form>
{result && (
<div className="atom-list">
{result.status === 'no_match' && <Quiet>Nothing in the store answers “{result.query}”.</Quiet>}
{result.hits.map((hit) => (
<AtomRow
key={hit.atom.atom_id}
atom={hit.atom}
meta={`${hit.final_score.toFixed(3)} · sparse ${hit.sparse_score.toFixed(2)} · visual ${hit.visual_score.toFixed(2)}`}
busy={busy === `forget-${hit.atom.atom_id}`}
onForget={() => submitForget(hit.atom)}
/>
))}
</div>
)}
<form className="stack" onSubmit={submitRemember}>
<label>
Tell it something
<input value={statement} onChange={(event) => setStatement(event.target.value)} placeholder="the spare glasses are in the hall drawer" />
</label>
<button className="action-button secondary" disabled={!statement || busy === 'remember'}>
<Plus size={16} />
Remember
</button>
</form>
<div className="atom-list">
{(page?.atoms ?? []).map((atom) => (
<AtomRow
key={atom.atom_id}
atom={atom}
meta={formatAgo(atom.event_time ?? atom.ingested_at)}
busy={busy === `forget-${atom.atom_id}`}
onForget={() => submitForget(atom)}
/>
))}
{page && page.atoms.length === 0 && <Quiet>The store is empty.</Quiet>}
</div>
<div className="pager">
<button className="icon-button" onClick={previousPage} disabled={history.length === 0} title="Previous page">
<ChevronLeft size={16} />
</button>
<small>
{page ? `${page.atoms.length} of ${formatNumber(page.total)} atoms` : 'loading'}
</small>
<button className="icon-button" onClick={nextPage} disabled={!page?.next_cursor} title="Next page">
<ChevronRight size={16} />
</button>
</div>
{notice && <div className="metric-strip"><span>{notice}</span></div>}
{error && <div className="error-line">{error}</div>}
</Panel>
);
}
function AtomRow({
atom,
meta,
busy,
onForget,
}: {
atom: EvidenceAtom;
meta: string;
busy: boolean;
onForget: () => void;
}): ReactNode {
return (
<article className="atom-row">
{atom.image_ref && <img className="thumb" src={atomImageUrl(atom.atom_id)} alt={atom.atom_id} loading="lazy" />}
<div className="atom-body">
<header>
<span>{atom.modality}</span>
<strong>{meta}</strong>
</header>
<p>{atom.text.slice(0, 200) || <em>no text on this atom</em>}</p>
<small>
{atom.holder_id || 'no holder'} · {atom.origin} · {atom.scenario || 'no scenario'} ·{' '}
{formatStamp(atom.event_time ?? atom.ingested_at)} · parser {atom.trust.parser.toFixed(2)}
</small>
</div>
<button className="icon-button" onClick={onForget} disabled={busy} title="Forget this memory">
<Trash2 size={16} />
</button>
</article>
);
}
+124
View File
@@ -0,0 +1,124 @@
import { GitBranch, Play, ShieldCheck } from 'lucide-react';
import { useEffect, useState } from 'react';
import { getLatestProofSuite, runHashHop, runProofSuite } from '../api';
import type { HashHopProof, ProofSuiteReport } from '../types';
import { errorMessage, formatNumber, shortHash } from '../lib/format';
import { Panel, Quiet } from './ui';
export function ProofPanel() {
const [proofSuite, setProofSuite] = useState<ProofSuiteReport | null>(null);
const [hashHop, setHashHop] = useState<HashHopProof | null>(null);
const [busy, setBusy] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
let cancelled = false;
async function loadLatest() {
try {
const latest = await getLatestProofSuite().catch(() => null);
if (!cancelled) {
setProofSuite(latest);
}
} catch (err) {
if (!cancelled) {
setError(errorMessage(err));
}
}
}
void loadLatest();
return () => {
cancelled = true;
};
}, []);
const passed = proofSuite?.checks.filter((check) => check.status === 'passed').length ?? 0;
async function submitSuite() {
setBusy('proof-suite');
setError(null);
try {
setProofSuite(await runProofSuite());
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
async function submitHashHop(kind: 'text' | 'visual') {
setBusy(`hashhop-${kind}`);
setError(null);
try {
setHashHop(await runHashHop(kind, 2, kind === 'visual' ? 262144 : 1010000));
} catch (err) {
setError(errorMessage(err));
} finally {
setBusy(null);
}
}
return (
<Panel title="PRD Proof Suite" icon={<ShieldCheck size={17} />}>
<div className="proof-suite-header">
<button className="action-button secondary" onClick={submitSuite} disabled={busy === 'proof-suite'}>
<Play size={16} />
Run Suite
</button>
<div className={proofSuite?.status === 'passed' ? 'proof-pill passed' : 'proof-pill'}>
{proofSuite ? `${passed}/${proofSuite.checks.length} passed` : 'pending'}
</div>
</div>
{proofSuite && (
<div className="proof-list">
{proofSuite.checks.map((check) => (
<article className="proof-row" key={check.name}>
<header>
<strong>{check.name}</strong>
<span className={check.status === 'passed' ? 'proof-status passed' : 'proof-status'}>{check.status}</span>
</header>
<p>{check.detail}</p>
<small>{check.evidence[0]}</small>
</article>
))}
<div className="proof-box">
<strong>{proofSuite.proof_id}</strong>
<span>{proofSuite.status}</span>
<small>{proofSuite.cartridge_id}</small>
<small>{proofSuite.dna_after ?? proofSuite.dna_before}</small>
</div>
</div>
)}
{!proofSuite && <Quiet>Proof suite has not run yet</Quiet>}
<div className="button-row">
<button
className="action-button secondary"
onClick={() => submitHashHop('visual')}
disabled={busy === 'hashhop-visual'}
>
<GitBranch size={15} />
Visual 2-hop
</button>
<button
className="action-button secondary"
onClick={() => submitHashHop('text')}
disabled={busy === 'hashhop-text'}
>
<GitBranch size={15} />
Text 2-hop
</button>
</div>
{hashHop && (
<div className="proof-box">
<strong>{shortHash(hashHop.proof_id)}</strong>
<span>{hashHop.kind}</span>
<span>{hashHop.hops} hops</span>
<span>{formatNumber(hashHop.token_equivalent)} token eq</span>
<small>{hashHop.expected_target_id}</small>
</div>
)}
{error && <div className="error-line">{error}</div>}
</Panel>
);
}
+57
View File
@@ -0,0 +1,57 @@
import { Eye } from 'lucide-react';
import type { SenseStatus } from '../types';
import { formatNumber } from '../lib/format';
import { Panel, Quiet } from './ui';
export function SensesPanel({ senses }: { senses: SenseStatus | null }) {
return (
<Panel title="Senses" icon={<Eye size={17} />}>
<div className="layer-list">
{senses && (
<>
<SenseRow
label="dense vectors"
state={senses.dense}
detail={`${formatNumber(senses.dense_covered)} of ${formatNumber(senses.store_atoms)} atoms indexed`}
/>
<SenseRow
label="picture embeddings"
state={senses.visual}
detail={
`${formatNumber(senses.picture_atoms)} pictures in the store` +
(senses.picture_bytes_missing > 0
? `, ${formatNumber(senses.picture_bytes_missing)} with no bytes behind them`
: '')
}
/>
<SenseRow
label="speech"
state={senses.speech}
detail={`${formatNumber(senses.audio_atoms)} audio atoms`}
/>
<SenseRow label="captioning" state={senses.captioning} detail="turns a wordless picture into text" />
</>
)}
{!senses && <Quiet>Waiting for status.</Quiet>}
</div>
{senses && (
<div className="adapter-metrics">
<small title={senses.clip_path ?? undefined}>{senses.clip_path ? `clip ${senses.clip_path}` : 'no CLIP snapshot configured'}</small>
<small title={senses.asr_path ?? undefined}>{senses.asr_path ? `asr ${senses.asr_path}` : 'no speech snapshot configured'}</small>
<small title={senses.vlm_path ?? undefined}>{senses.vlm_path ? `vlm ${senses.vlm_path}` : 'no captioning model configured'}</small>
</div>
)}
</Panel>
);
}
function SenseRow({ label, state, detail }: { label: string; state: string; detail: string }) {
return (
<div className="layer-row">
<span>{label}</span>
<strong>{state}</strong>
<small>{detail}</small>
</div>
);
}
+35
View File
@@ -0,0 +1,35 @@
import { ReactNode } from 'react';
export function Panel({ title, icon, children }: { title: string; icon: ReactNode; children: ReactNode }) {
return (
<section className="panel">
<header className="panel-header">
<span className="panel-icon">{icon}</span>
<h2>{title}</h2>
</header>
{children}
</section>
);
}
export function Kpi({ icon, label, value, detail }: { icon: ReactNode; label: string; value: string; detail: string }) {
return (
<section className="kpi">
<span className="panel-icon">{icon}</span>
<div>
<p>{label}</p>
<strong>{value}</strong>
<small>{detail}</small>
</div>
</section>
);
}
export function Quiet({ children }: { children: ReactNode }) {
return <div className="quiet-line">{children}</div>;
}
export function Pill({ state, children }: { state?: 'passed' | 'failed' | string; children: ReactNode }) {
const tone = state === 'passed' || state === 'ready' || state === 'loaded' || state === 'current' ? ' passed' : '';
return <span className={`proof-pill${tone}`}>{children}</span>;
}
+96
View File
@@ -0,0 +1,96 @@
import type { AdapterStatus, SystemStatus } from '../types';
export function errorMessage(err: unknown): string {
if (err instanceof Error) {
return err.message;
}
return String(err);
}
export function formatNumber(value: number): string {
return new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1 }).format(value);
}
export function formatBytes(value: number): string {
if (value < 1024) {
return `${value} B`;
}
if (value < 1024 * 1024) {
return `${(value / 1024).toFixed(1)} KiB`;
}
return `${(value / 1024 / 1024).toFixed(1)} MiB`;
}
export function formatDuration(value: number | null): string {
if (typeof value !== 'number') {
return 'time pending';
}
if (value < 60) {
return `${value.toFixed(1)}s`;
}
return `${Math.round(value / 60)}m`;
}
export function shortHash(value: string): string {
return value.slice(0, 8);
}
export function formatOptimizer(adapter: AdapterStatus): string {
if (adapter.optimizer === 'paged_adamw_8bit') {
return 'paged 8-bit AdamW';
}
return adapter.optimizer_family ?? adapter.optimizer ?? 'optimizer pending';
}
export function formatFramework(value: string): string {
if (value === 'unsloth_patched_transformers_peft') {
return 'Unsloth patch + PEFT';
}
return value;
}
export function formatCheckpointing(adapter: AdapterStatus): string {
if (adapter.gradient_checkpointing_mode === 'unsloth') {
return 'ckpt unsloth';
}
return adapter.gradient_checkpointing ? 'ckpt on' : 'ckpt pending';
}
export function formatRuntimeDetail(status: SystemStatus | null): string {
const model = status?.runtime.model_id ?? 'Qwen/Qwen3.5-9B';
const adapter = status?.runtime.adapter_kind?.replaceAll('_', '-');
return adapter ? `${model} · ${adapter}` : model;
}
export function formatVram(status: SystemStatus | null): string {
const total = status?.runtime.vram_total_mb;
const used = status?.runtime.vram_used_mb;
if (typeof total === 'number' && typeof used === 'number') {
return `${used} / ${total} MiB`;
}
return status?.runtime.cuda ?? 'CUDA';
}
export function formatStamp(iso: string | null): string {
if (!iso) {
return 'no time given';
}
return `${iso.slice(0, 10)} ${iso.slice(11, 16)}Z`;
}
export function formatAgo(iso: string | null): string {
if (!iso) {
return 'undated';
}
const seconds = Math.round((Date.now() - new Date(iso).getTime()) / 1000);
if (seconds < 60) {
return 'just now';
}
const units: Array<[number, string]> = [[3600, 'h'], [86400, 'd'], [2592000, 'mo'], [31536000, 'y']];
for (const [size, name] of units.slice().reverse()) {
if (seconds >= size) {
return `${Math.floor(seconds / size)}${name} ago`;
}
}
return `${Math.floor(seconds / 60)}m ago`;
}
+48
View File
@@ -442,3 +442,51 @@ meter {
align-items: flex-start;
}
}
.atom-row {
display: flex;
gap: 9px;
align-items: flex-start;
}
.atom-body {
display: grid;
gap: 4px;
flex: 1;
min-width: 0;
}
.atom-body header {
display: flex;
justify-content: space-between;
gap: 12px;
}
.atom-body p,
.atom-body small {
margin: 0;
overflow-wrap: anywhere;
}
.thumb {
width: 72px;
height: 72px;
object-fit: cover;
border: 1px solid #d7ded2;
border-radius: 6px;
background: #ffffff;
}
.filter-row {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 8px;
}
.pager {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-top: 4px;
}
+136 -9
View File
@@ -32,11 +32,27 @@ export interface MemoryStatus {
layers: CacheLayerStatus[];
}
export interface SenseStatus {
dense: 'off' | 'missing' | 'behind' | 'current';
dense_covered: number;
store_atoms: number;
picture_atoms: number;
picture_bytes_missing: number;
visual: 'absent' | 'stale' | 'ready';
audio_atoms: number;
speech: 'absent' | 'missing' | 'ready';
captioning: 'absent' | 'missing' | 'ready';
clip_path: string | null;
asr_path: string | null;
vlm_path: string | null;
}
export interface SystemStatus {
app: string;
version: string;
runtime: RuntimeStatus;
memory: MemoryStatus;
senses: SenseStatus;
profiles: Record<string, Record<string, unknown>>;
data_home: string;
}
@@ -108,24 +124,65 @@ export interface LayoutBox {
frame_second?: number | null;
}
export interface TrustScores {
parser: number;
ocr: number;
model: number;
}
export interface EvidenceAtom {
atom_id: string;
modality: string;
source_id: string;
source: string;
text: string;
image_ref: string | null;
layout: LayoutBox | null;
token_equivalent: number;
ingested_at: string;
holder_id: string;
origin: string;
scenario: string;
event_time: string | null;
event_time_precision: string;
valid_from: string | null;
valid_to: string | null;
trust: TrustScores;
}
export interface AtomPage {
atoms: EvidenceAtom[];
total: number;
next_cursor: string | null;
}
export interface SearchFilters {
holder?: string | null;
as_holder?: string | null;
scenario?: string | null;
source_id?: string | null;
modality?: string | null;
since?: string | null;
until?: string | null;
min_trust?: number | null;
}
export interface RetrievalHit {
atom: EvidenceAtom;
sparse_score: number;
dense_score: number;
visual_score: number;
graph_score: number;
final_score: number;
}
export interface SearchResult {
query: string;
status: 'hits' | 'no_match';
hits: RetrievalHit[];
next_cursor: string | null;
}
export interface AnswerResponse {
answer: string;
citations: string[];
@@ -176,13 +233,83 @@ export interface ProofSuiteReport {
dna_after: string | null;
}
export interface MemoryMap {
atoms: EvidenceAtom[];
layers: CacheLayerStatus[];
cartridges: Array<{
cartridge_id: string;
name: string;
token_equivalent: number;
dna: string | null;
}>;
export interface CartridgeManifest {
cartridge_id: string;
name: string;
created_at: string;
model_base: string;
source_count: number;
atom_count: number;
token_equivalent: number;
artifacts: Record<string, string>;
kv_fingerprint: Record<string, unknown> | null;
dna: string | null;
}
export interface MountState {
mounted: string[];
scoped: boolean;
}
export interface AdapterChoice {
kind: string;
state: 'loaded' | 'available' | 'deferred' | 'missing';
reason: string;
path: string | null;
adapter_id: string | null;
base_model: string | null;
origin: 'library' | 'cartridge' | null;
cartridge_id: string | null;
shadowed: boolean;
}
export interface AdapterLoadReport {
model_id: string;
mounted: string[];
adapters: AdapterChoice[];
}
export interface RuntimeLaunchProfile {
name: string;
runtime: string;
role: string;
context_tokens: number;
script: string;
command: string[];
environment: Record<string, string>;
required_features: string[];
}
export interface RuntimeProfileValidation {
name: string;
runtime: string;
status: 'ready' | 'missing';
script_exists: boolean;
package: string | null;
package_version: string | null;
executable: string | null;
gpu_available: boolean;
probe_command: string[];
probe_status: 'passed' | 'failed' | 'skipped';
probe_exit_code: number | null;
probe_output: string | null;
detail: string;
}
export interface RuntimeProfileReport {
status: 'ready' | 'incomplete';
created_at: string;
profiles: RuntimeLaunchProfile[];
validations: RuntimeProfileValidation[];
}
export interface ForgetReport {
source_id: string;
atom_ids: string[];
atoms_deleted: number;
edges_deleted: number;
cache_entries_cleared: number;
vector_index_dropped: boolean;
affected_cartridges: Array<Record<string, unknown>>;
reason: string;
}