feat(CC-079): add Agent Center page (8 agent templates with tool mapping + Hermes architecture)
This commit is contained in:
parent
6cafc2ea9d
commit
9857b027c1
1 changed files with 178 additions and 0 deletions
178
src/app/dashboard/agents/page.tsx
Normal file
178
src/app/dashboard/agents/page.tsx
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
'use client';
|
||||
|
||||
import { useState } 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 DataSource { id: string; name: string; type: string; status: string; }
|
||||
|
||||
interface AgentTemplate {
|
||||
id: string; name: string; description: string; icon: string;
|
||||
tools: string[]; category: string; endpoint: string | null; status: 'active' | 'planned';
|
||||
}
|
||||
|
||||
const AGENTS: AgentTemplate[] = [
|
||||
{
|
||||
id: 'research', name: 'Research Agent', description: 'Caută și sintetizează informații despre companii, persoane sau subiecte.',
|
||||
icon: '🔍', tools: ['AnythingLLM', 'ClickHouse', 'OpenRouter'], category: 'Intelligence',
|
||||
endpoint: '/v1/intelligence/companies/search', status: 'active',
|
||||
},
|
||||
{
|
||||
id: 'document', name: 'Document Analyst', description: 'Analizează documente, extrage entități, clasifică și rezumă.',
|
||||
icon: '📄', tools: ['Hermes', 'AnythingLLM'], category: 'Documents',
|
||||
endpoint: null, status: 'planned',
|
||||
},
|
||||
{
|
||||
id: 'financial', name: 'Financial Advisor', description: 'Analizează tranzacții, detectează anomalii, proiectează cashflow.',
|
||||
icon: '💰', tools: ['ClickHouse', 'Hermes', 'OpenRouter'], category: 'Finance',
|
||||
endpoint: null, status: 'planned',
|
||||
},
|
||||
{
|
||||
id: 'crm', name: 'CRM Intelligence', description: 'Sugerează urmăriri, detectează relații reci, prioritizează contacte.',
|
||||
icon: '🤝', tools: ['Hermes', 'ClickHouse'], category: 'CRM',
|
||||
endpoint: null, status: 'planned',
|
||||
},
|
||||
{
|
||||
id: 'compliance', name: 'Compliance Monitor', description: 'Verifică GDPR, detectează inconsistențe în clasificarea datelor, alertează.',
|
||||
icon: '🛡️', tools: ['ClickHouse', 'Hermes'], category: 'Privacy',
|
||||
endpoint: null, status: 'planned',
|
||||
},
|
||||
{
|
||||
id: 'scheduler', name: 'Action Scheduler', description: 'Propune, programează și monitorizează acțiuni AI cu aprobare umană.',
|
||||
icon: '🤖', tools: ['Hermes', 'n8n', 'CEO OS API'], category: 'Automation',
|
||||
endpoint: '/v1/approvals', status: 'active',
|
||||
},
|
||||
{
|
||||
id: 'email', name: 'Email Drafter', description: 'Redactează emailuri pe baza contextului din CRM, documente și conversații.',
|
||||
icon: '✉️', tools: ['Hermes', 'OpenRouter'], category: 'Communication',
|
||||
endpoint: null, status: 'planned',
|
||||
},
|
||||
{
|
||||
id: 'opportunity', name: 'Opportunity Scout', description: 'Scanează surse externe, identifică oportunități relevante pentru profilul utilizatorului.',
|
||||
icon: '🎯', tools: ['Hermes', 'AnythingLLM', 'ClickHouse'], category: 'Growth',
|
||||
endpoint: null, status: 'planned',
|
||||
},
|
||||
];
|
||||
|
||||
const CATEGORIES = ['all', 'Intelligence', 'Documents', 'Finance', 'CRM', 'Privacy', 'Automation', 'Communication', 'Growth'];
|
||||
|
||||
export default function AgentCenterPage() {
|
||||
const { activeTenant } = useSession();
|
||||
const tenantId = activeTenant?.tenantId ?? '';
|
||||
const [category, setCategory] = useState('all');
|
||||
const [selected, setSelected] = useState<AgentTemplate | null>(null);
|
||||
|
||||
const { data: dataSources = [] } = useQuery({
|
||||
queryKey: ['agent-sources', tenantId],
|
||||
queryFn: () => apiFetch<DataSource[]>('/v1/data-sources', { tenantId }),
|
||||
enabled: Boolean(tenantId), staleTime: 120_000,
|
||||
});
|
||||
|
||||
const filtered = AGENTS.filter((a) => category === 'all' || a.category === category);
|
||||
const active = AGENTS.filter((a) => a.status === 'active').length;
|
||||
|
||||
return (
|
||||
<div className="max-w-5xl space-y-6 p-6">
|
||||
<div>
|
||||
<h1 className="font-display text-2xl font-semibold text-ink">Agent Center</h1>
|
||||
<p className="text-sm text-ink-faint mt-1">
|
||||
{active} agenți activi · {AGENTS.length - active} planificați · Rutați prin Hermes
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Architecture note */}
|
||||
<div className="card p-4 bg-primary/5 border-primary/20 space-y-1">
|
||||
<p className="text-xs font-semibold text-ink">Arhitectură CEO OS AI</p>
|
||||
<p className="text-xs text-ink-faint">
|
||||
Toate cererile AI sunt rutate prin <strong>Hermes</strong> (152.53.112.35) pentru real-time learning și customizare per client.
|
||||
Hermes orchestrează OpenRouter → Gemini / NVIDIA ca fallback.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2 mt-2">
|
||||
{['Hermes', 'OpenRouter', 'AnythingLLM', 'ClickHouse', 'n8n'].map((tool) => (
|
||||
<span key={tool} className="rounded-full bg-muted px-2 py-0.5 text-[9px] text-ink-faint">{tool}</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Category filter */}
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{CATEGORIES.map((c) => (
|
||||
<button key={c} onClick={() => setCategory(c)}
|
||||
className={`rounded-full border px-3 py-1 text-xs ${category === c ? 'bg-primary/10 border-primary text-ink' : 'bg-card border-border text-ink-faint'}`}>
|
||||
{c === 'all' ? 'Toți' : c}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 lg:grid-cols-3">
|
||||
<div className="lg:col-span-2 grid gap-3 sm:grid-cols-2">
|
||||
{filtered.map((agent) => (
|
||||
<button key={agent.id} onClick={() => setSelected(agent)}
|
||||
className={`card p-4 text-left hover:border-primary/40 transition-colors ${selected?.id === agent.id ? 'border-primary/50 bg-primary/5' : ''}`}>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<span className="text-xl">{agent.icon}</span>
|
||||
<span className="text-sm font-medium text-ink">{agent.name}</span>
|
||||
<span className={`ml-auto rounded-full px-1.5 py-0.5 text-[8px] font-bold ${agent.status === 'active' ? 'bg-signal-ok/10 text-signal-ok' : 'bg-muted text-ink-faint'}`}>
|
||||
{agent.status}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-[10px] text-ink-faint line-clamp-2">{agent.description}</p>
|
||||
<div className="flex flex-wrap gap-1 mt-2">
|
||||
{agent.tools.slice(0, 3).map((t) => (
|
||||
<span key={t} className="rounded-full bg-muted px-1.5 py-0.5 text-[8px] text-ink-faint">{t}</span>
|
||||
))}
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{selected ? (
|
||||
<div className="card p-5 space-y-4 sticky top-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-2xl">{selected.icon}</span>
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-ink">{selected.name}</p>
|
||||
<p className="text-[10px] text-ink-faint">{selected.category}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs text-ink-faint">{selected.description}</p>
|
||||
<div className="space-y-1">
|
||||
<p className="text-[10px] font-semibold text-ink-faint">Instrumente</p>
|
||||
{selected.tools.map((t) => (
|
||||
<div key={t} className="flex items-center gap-2">
|
||||
<span className={`w-1.5 h-1.5 rounded-full ${dataSources.some((ds) => ds.name.toLowerCase().includes(t.toLowerCase())) ? 'bg-signal-ok' : 'bg-border'}`} />
|
||||
<span className="text-xs text-ink">{t}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{selected.endpoint && (
|
||||
<div className="text-[10px] text-ink-faint border-t border-border/50 pt-3">
|
||||
<p className="font-semibold mb-0.5">Endpoint activ</p>
|
||||
<code className="bg-muted px-1 py-0.5 rounded">{selected.endpoint}</code>
|
||||
</div>
|
||||
)}
|
||||
{selected.status === 'active' ? (
|
||||
<Link href={selected.endpoint ? `/dashboard/ai/approvals` : '#'}
|
||||
className="block w-full rounded-lg bg-primary px-4 py-2 text-center text-sm font-medium text-white hover:bg-primary/90">
|
||||
Deschide →
|
||||
</Link>
|
||||
) : (
|
||||
<div className="rounded-lg bg-muted px-4 py-2 text-center text-xs text-ink-faint">
|
||||
În planificare — A4
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="card p-6 text-center space-y-2">
|
||||
<p className="text-2xl">🤖</p>
|
||||
<p className="text-xs text-ink-faint">Selectează un agent.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue