import { headers } from 'next/headers'; import Dashboard from '@/components/dashboard'; import { agent, handlers, runtime } from '@/lib/agent'; import type { DashboardData } from '@/lib/dashboard-types'; import type { AgentHealth } from '@/lib/api'; const BASE_PATH = '/api/agent'; function ensureSerializable(value: T): T { try { return JSON.parse(JSON.stringify(value)) as T; } catch (error) { throw new Error(`Object contains non-serializable values: ${error}`); } } async function getRequestOrigin(): Promise { const headerMap = await headers(); const proto = headerMap.get('x-forwarded-proto') ?? 'http'; const host = headerMap.get('host') ?? 'localhost:3000'; return `${proto}://${host}`; } type DashboardPayload = { dashboard: DashboardData; manifestText: string; origin: string; }; function normalizeOrigin(value: unknown): string { if (typeof value === 'string' && value.length > 0) { return value; } if (value instanceof URL) { return value.origin; } if (value && typeof value === 'object') { const originProp = (value as { origin?: unknown }).origin; if (typeof originProp === 'string' && originProp.length > 0) { return originProp; } if (originProp instanceof URL) { return originProp.origin; } } return 'http://localhost:3000'; } async function loadDashboardPayload(origin: string): Promise { const resolvedOrigin = normalizeOrigin(origin); const manifest = ensureSerializable(runtime.manifest.build(resolvedOrigin)); const manifestEntrypoints = manifest.entrypoints || []; const rawEntrypoints = agent.listEntrypoints(); const entrypoints = rawEntrypoints.map(entry => { const manifestEntry = manifestEntrypoints.find( (candidate: any) => candidate.key === entry.key ); return { key: String(entry.key), description: entry.description ? String(entry.description) : null, streaming: Boolean(entry.stream), price: typeof entry.price === 'string' ? String(entry.price) : entry.price ? { invoke: entry.price.invoke ? String(entry.price.invoke) : null, stream: entry.price.stream ? String(entry.price.stream) : null, } : null, network: entry.network ? String(entry.network) : null, inputSchema: manifestEntry?.input || null, outputSchema: manifestEntry?.output || null, }; }); const configPayments = runtime.payments?.config; const payments = configPayments !== undefined ? { network: configPayments.network ? String(configPayments.network) : null, defaultPrice: configPayments.defaultPrice ? String(configPayments.defaultPrice) : null, payTo: configPayments.payTo ? String(configPayments.payTo) : null, } : null; const rawMeta = agent.config.meta; const meta = rawMeta ? { name: String(rawMeta.name || ''), version: String(rawMeta.version || ''), description: rawMeta.description ? String(rawMeta.description) : null, } : null; return { dashboard: ensureSerializable({ meta, payments, entrypoints }), manifestText: JSON.stringify(manifest, null, 2), origin: resolvedOrigin, }; } async function loadInitialHealth(): Promise { if (!handlers.health) return null; try { const response = await handlers.health( new Request('http://agent.local/api/agent/health') ); const payload = await response.json(); if (!payload || typeof payload !== 'object') { return null; } return { ...(payload as AgentHealth), timestamp: typeof (payload as AgentHealth).timestamp === 'string' ? (payload as AgentHealth).timestamp : new Date().toISOString(), }; } catch { return null; } } export default async function Page() { const origin = await getRequestOrigin(); const [{ dashboard, manifestText, origin: resolvedOrigin }, initialHealth] = await Promise.all([loadDashboardPayload(origin), loadInitialHealth()]); return ( ); }