Files
blackroad-os-prism-console/app/agents/page.tsx
Alexa Louise 1655047a04 Add Agents, Intents, and Ledger pages to Prism Console
- Add /agents page with agent cards showing status, type, trust score
- Add /intents page to track declared intentions
- Add /ledger page with immutable event log display
- Update layout with navigation menu
- All pages fetch from api.blackroad.io

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-14 19:01:07 -06:00

132 lines
3.5 KiB
TypeScript

import { Suspense } from 'react';
interface Agent {
id: string;
identity: string;
name?: string;
type: 'human' | 'ai' | 'system' | 'hybrid';
status: 'observing' | 'active' | 'sleeping' | 'suspended';
trustScore: number;
lastSeen: string;
}
async function fetchAgents(): Promise<Agent[]> {
try {
const res = await fetch('https://api.blackroad.io/agents', {
next: { revalidate: 30 },
});
if (!res.ok) return [];
const data = await res.json();
return data.agents || [];
} catch (error) {
console.error('Failed to fetch agents:', error);
return [];
}
}
function AgentCard({ agent }: { agent: Agent }) {
const statusColors = {
active: 'bg-green-500/10 text-green-400 border-green-500/20',
observing: 'bg-blue-500/10 text-blue-400 border-blue-500/20',
sleeping: 'bg-gray-500/10 text-gray-400 border-gray-500/20',
suspended: 'bg-red-500/10 text-red-400 border-red-500/20',
};
const typeIcons = {
human: '👤',
ai: '🤖',
system: '⚙️',
hybrid: '🧬',
};
return (
<div className="card-surface p-4 hover:border-gray-600 transition-colors">
<div className="flex items-start justify-between">
<div className="flex items-center gap-3">
<span className="text-2xl">{typeIcons[agent.type]}</span>
<div>
<h3 className="font-medium text-white">
{agent.name || agent.identity}
</h3>
<p className="text-xs text-gray-500 font-mono">{agent.identity}</p>
</div>
</div>
<div
className={`px-2 py-1 rounded border text-xs font-medium ${
statusColors[agent.status]
}`}
>
{agent.status}
</div>
</div>
<div className="mt-4 grid grid-cols-2 gap-4 text-sm">
<div>
<p className="text-gray-400">Type</p>
<p className="text-white capitalize">{agent.type}</p>
</div>
<div>
<p className="text-gray-400">Trust Score</p>
<p className="text-white">{agent.trustScore.toFixed(1)}%</p>
</div>
</div>
<div className="mt-3 text-xs text-gray-500">
Last seen: {new Date(agent.lastSeen).toLocaleString()}
</div>
</div>
);
}
async function AgentsList() {
const agents = await fetchAgents();
if (agents.length === 0) {
return (
<div className="card-surface p-8 text-center">
<p className="text-gray-400">No agents found</p>
<p className="text-sm text-gray-500 mt-2">
Agents will appear here once they connect to the mesh
</p>
</div>
);
}
return (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{agents.map((agent) => (
<AgentCard key={agent.id} agent={agent} />
))}
</div>
);
}
export default function AgentsPage() {
return (
<div className="flex flex-col gap-6">
<section className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-white">Agents</h1>
<p className="text-gray-400 mt-1">
Monitor and manage agents in the BlackRoad mesh
</p>
</div>
<button className="btn-primary">
<span>+</span>
<span>New Agent</span>
</button>
</section>
<Suspense
fallback={
<div className="card-surface p-8 text-center text-gray-400">
Loading agents...
</div>
}
>
<AgentsList />
</Suspense>
</div>
);
}