95 lines
5.8 KiB
TypeScript
95 lines
5.8 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from 'framer-motion';
|
|
import { TerminalSquare, Filter, RefreshCw, Cpu, Brain, Zap } from 'lucide-react';
|
|
|
|
const mockLogs = [
|
|
{ id: 1, time: '10:41:30', agent: 'Analyst', type: 'REJECT', cost: '$0.0012', prompt: 'Evaluate lot: "RTX 4090 Box Only" against criteria...', response: '{"verdict": "REJECT", "reason": "Listing explicitly states \'Box Only\', violating target criteria."}' },
|
|
{ id: 2, time: '10:40:12', agent: 'Analyst', type: 'APPROVE', cost: '$0.0025', prompt: 'Evaluate lot: "ThinkPad T14 Gen 3" against criteria...', response: '{"verdict": "APPROVE", "reason": "Matches specs, good condition, price $450 is significantly below $800 avg."}' },
|
|
{ id: 3, time: '10:39:45', agent: 'Strategist', type: 'OPTIMIZE', cost: '$0.0050', prompt: 'Analyze last 24h win rates on ShopGoodwill...', response: '{"action": "UPDATE_SCHEDULE", "target": "ShopGoodwill", "new_cron": "0 * * * *"}' },
|
|
{ id: 4, time: '10:35:10', agent: 'Scout', type: 'INFO', cost: '$0.0005', prompt: 'Parse unstructured layout changes on eBay UK...', response: '{"action": "SELECTORS_UPDATED", "confidence": 0.98 }' },
|
|
];
|
|
|
|
export default function AILogPage() {
|
|
return (
|
|
<div className="container mx-auto px-6 py-12 h-[calc(100vh-80px)] flex flex-col">
|
|
<div className="flex flex-col md:flex-row justify-between items-start md:items-center mb-8 shrink-0 gap-4">
|
|
<div>
|
|
<h1 className="text-4xl font-extrabold tracking-tight mb-2 flex items-center gap-3">
|
|
Neural Telemetry <span className="text-primary"><Brain className="w-8 h-8" /></span>
|
|
</h1>
|
|
<p className="text-muted-foreground text-lg">Raw input/output logs from all connected LLM agents.</p>
|
|
</div>
|
|
<div className="flex gap-3">
|
|
<button className="flex items-center gap-2 px-5 py-2.5 bg-secondary hover:bg-secondary/80 border-2 border-border/50 rounded-full font-bold transition-all hover:scale-105 shadow-sm">
|
|
<Filter className="w-4 h-4" /> Filter
|
|
</button>
|
|
<button className="flex items-center gap-2 px-5 py-2.5 bg-primary hover:bg-primary/90 text-primary-foreground rounded-full font-bold transition-all hover:scale-105 shadow-lg hover:shadow-primary/30">
|
|
<RefreshCw className="w-4 h-4" /> Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex-1 bg-card border-2 border-border/50 rounded-3xl overflow-hidden flex flex-col shadow-sm">
|
|
<div className="grid grid-cols-12 gap-4 p-5 border-b-2 border-border/50 bg-secondary/30 text-sm font-bold text-muted-foreground uppercase tracking-wider shrink-0">
|
|
<div className="col-span-2 md:col-span-2">Time / Agent</div>
|
|
<div className="col-span-2 md:col-span-1">Action</div>
|
|
<div className="col-span-4 md:col-span-4">Prompt Context</div>
|
|
<div className="col-span-4 md:col-span-4">JSON Response</div>
|
|
<div className="hidden md:flex col-span-1 justify-end">Est. Cost</div>
|
|
</div>
|
|
|
|
<div className="flex-1 overflow-auto p-4 space-y-3 custom-scrollbar">
|
|
{mockLogs.map((log, i) => (
|
|
<motion.div
|
|
key={log.id}
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ delay: i * 0.1, type: "spring" }}
|
|
className="grid grid-cols-12 gap-4 p-4 bg-secondary/20 hover:bg-secondary/50 border border-border/30 rounded-2xl transition-colors cursor-pointer group"
|
|
>
|
|
<div className="col-span-2 md:col-span-2 flex flex-col justify-center">
|
|
<span className="font-bold text-foreground">{log.time}</span>
|
|
<span className="text-xs font-semibold text-muted-foreground flex items-center gap-1 mt-1">
|
|
{log.agent === 'Analyst' ? <Brain className="w-3 h-3 text-purple-500" /> : log.agent === 'Strategist' ? <Zap className="w-3 h-3 text-amber-500" /> : <Cpu className="w-3 h-3 text-blue-500" />}
|
|
{log.agent}
|
|
</span>
|
|
</div>
|
|
<div className="col-span-2 md:col-span-1 flex items-center">
|
|
<span className={`px-3 py-1 rounded-full text-xs font-bold ${
|
|
log.type === 'APPROVE' ? 'bg-green-500/10 text-green-600 dark:text-green-400' :
|
|
log.type === 'REJECT' ? 'bg-red-500/10 text-red-600 dark:text-red-400' :
|
|
log.type === 'OPTIMIZE' ? 'bg-amber-500/10 text-amber-600 dark:text-amber-400' :
|
|
'bg-blue-500/10 text-blue-600 dark:text-blue-400'
|
|
}`}>
|
|
{log.type}
|
|
</span>
|
|
</div>
|
|
<div className="col-span-4 md:col-span-4 text-muted-foreground text-sm flex items-center truncate font-medium pr-4">
|
|
{log.prompt}
|
|
</div>
|
|
<div className="col-span-4 md:col-span-4 text-sm flex items-center truncate font-mono text-foreground/80 bg-background/50 px-3 py-1.5 rounded-lg border border-border/30">
|
|
{log.response}
|
|
</div>
|
|
<div className="hidden md:flex col-span-1 items-center justify-end text-sm font-bold text-muted-foreground group-hover:text-primary transition-colors">
|
|
{log.cost}
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
transition={{ delay: 0.5 }}
|
|
className="text-center p-12 text-muted-foreground flex flex-col items-center justify-center gap-4"
|
|
>
|
|
<div className="p-4 bg-secondary/30 rounded-full animate-pulse">
|
|
<TerminalSquare className="w-8 h-8 text-muted-foreground/50" />
|
|
</div>
|
|
<span className="font-medium text-lg">End of stream. Awaiting new neural inferences...</span>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |