feat(CC-083): add Memory & Knowledge page (AGE placeholder + current knowledge modules)
This commit is contained in:
parent
5a124fd015
commit
de0a635069
1 changed files with 100 additions and 0 deletions
100
src/app/dashboard/memory/page.tsx
Normal file
100
src/app/dashboard/memory/page.tsx
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import Link from 'next/link';
|
||||
import { apiFetch } from '../../../lib/api';
|
||||
import { useSession } from '../../../components/session-provider';
|
||||
|
||||
interface ResearchBrief { id: string; title: string; subjectType: string | null; subjectId: string | null; tags: string[]; createdAt: string; }
|
||||
interface Decision { id: string; title: string; rationale: string | null; tags: string[]; createdAt: string; }
|
||||
interface Observation { id: string; metric: string; value: string; subjectType: string; source: string | null; createdAt: string; }
|
||||
|
||||
export default function MemoryKnowledgePage() {
|
||||
const { activeTenant } = useSession();
|
||||
const tenantId = activeTenant?.tenantId ?? '';
|
||||
|
||||
const { data: briefs = [] } = useQuery({ queryKey: ['mem-briefs', tenantId], queryFn: () => apiFetch<ResearchBrief[]>('/v1/research-briefs', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000 });
|
||||
const { data: decisions = [] } = useQuery({ queryKey: ['mem-decisions', tenantId], queryFn: () => apiFetch<Decision[]>('/v1/decisions?limit=200', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000 });
|
||||
const { data: observations = [] } = useQuery({ queryKey: ['mem-obs', tenantId], queryFn: () => apiFetch<Observation[]>('/v1/observations', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000 });
|
||||
|
||||
const stats = useMemo(() => {
|
||||
const facts = observations.filter((o) => o.source && o.source.trim().length > 0);
|
||||
const uniqueTypes = new Set(observations.map((o) => o.subjectType)).size;
|
||||
const uniqueMetrics = new Set(observations.map((o) => o.metric)).size;
|
||||
const withRationale = decisions.filter((d) => d.rationale && d.rationale.length > 20);
|
||||
return { facts, uniqueTypes, uniqueMetrics, withRationale };
|
||||
}, [observations, decisions]);
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl space-y-6 p-6">
|
||||
<div>
|
||||
<h1 className="font-display text-2xl font-semibold text-ink">Memory & Knowledge</h1>
|
||||
<p className="text-sm text-ink-faint mt-1">Graf de cunoaștere CEO OS — fapte, relații și context cu provenance.</p>
|
||||
</div>
|
||||
|
||||
<div className="card p-4 bg-warn/5 border-warn/30 space-y-1">
|
||||
<p className="text-xs font-semibold text-warn">Apache AGE — neconectat la ceo-api</p>
|
||||
<p className="text-xs text-ink-faint">
|
||||
Apache AGE (PostgreSQL extension for graph queries) rulează pe server.
|
||||
Conexiunea la ceo-api și UI-ul graf complet (entități/relații/provenance) sunt în dezvoltare.
|
||||
Datele curente sunt stocate în PostgreSQL standard și accesibile prin modulele de mai jos.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Current knowledge stats */}
|
||||
<div className="grid grid-cols-2 gap-3 sm:grid-cols-4">
|
||||
<div className="card p-4 text-center">
|
||||
<p className="text-2xl font-bold text-ink">{observations.length}</p>
|
||||
<p className="text-[10px] text-ink-faint">fapte logate</p>
|
||||
</div>
|
||||
<div className="card p-4 text-center">
|
||||
<p className="text-2xl font-bold text-ink">{briefs.length}</p>
|
||||
<p className="text-[10px] text-ink-faint">research briefs</p>
|
||||
</div>
|
||||
<div className="card p-4 text-center">
|
||||
<p className="text-2xl font-bold text-ink">{stats.withRationale.length}</p>
|
||||
<p className="text-[10px] text-ink-faint">decizii documentate</p>
|
||||
</div>
|
||||
<div className="card p-4 text-center">
|
||||
<p className="text-2xl font-bold text-ink">{stats.uniqueMetrics}</p>
|
||||
<p className="text-[10px] text-ink-faint">tipuri metrici</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Modules currently available */}
|
||||
<div className="space-y-2">
|
||||
<p className="text-xs font-semibold uppercase tracking-wider text-ink-faint">Module de cunoaștere disponibile acum</p>
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
{[
|
||||
{ label: 'Research Briefs', href: '/dashboard/intelligence/insights', desc: `${briefs.length} briefs`, icon: '📚' },
|
||||
{ label: 'Decizii documentate', href: '/dashboard/decisions', desc: `${stats.withRationale.length} cu rațional`, icon: '🧠' },
|
||||
{ label: 'Observații personale', href: '/dashboard/personal-kpi', desc: `${observations.length} fapte`, icon: '📊' },
|
||||
{ label: 'Intelligence Persoane', href: '/dashboard/intelligence/people', desc: 'Contacte + observații', icon: '👤' },
|
||||
{ label: 'Intelligence Companii', href: '/dashboard/intelligence/companies', desc: 'ClickHouse 147M+', icon: '🏢' },
|
||||
{ label: 'AnythingLLM RAG', href: '/dashboard/integrations', desc: 'Q&A pe documente', icon: '🔍' },
|
||||
].map((m) => (
|
||||
<Link key={m.href} href={m.href} className="card p-4 flex items-center gap-3 hover:border-primary/40 transition-colors">
|
||||
<span className="text-2xl">{m.icon}</span>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-ink">{m.label}</p>
|
||||
<p className="text-[10px] text-ink-faint">{m.desc}</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Architecture note */}
|
||||
<div className="card p-4 bg-primary/5 border-primary/20 space-y-2">
|
||||
<p className="text-xs font-semibold text-ink">Arhitectură Memory Graph (planificată)</p>
|
||||
<div className="text-[10px] text-ink-faint space-y-1 font-mono">
|
||||
<p>PostgreSQL + Apache AGE → Cypher queries</p>
|
||||
<p>Entități: Person, Company, Document, Decision, Observation</p>
|
||||
<p>Relații: WORKS_AT, MENTIONED_IN, SUPPORTS, CONFLICTS_WITH, CAUSED_BY</p>
|
||||
<p>Provenance: source + timestamp + confidence pe fiecare fap</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue