import { createFileRoute } from '@tanstack/react-router'; import { useWalletClient } from 'wagmi'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { getHealth, getManifest, invokeEntrypointWithBody, streamEntrypointWithBody, type AgentHealth, type AgentPayments, } from '@/lib/api'; import { WalletSummary } from '@/components/wallet-summary'; import { getNetworkInfo } from '@/lib/network'; import { cn } from '@/lib/utils'; import { SchemaForm } from '@/components/schema-form'; type DashboardEntry = { key: string; description?: string | null; streaming: boolean; price?: string | { invoke?: string | null; stream?: string | null } | null; network?: string | null; inputSchema?: Record | null; outputSchema?: Record | null; }; type DashboardData = { meta: { name: string; version: string; description?: string | null; } | null; payments: AgentPayments | null; entrypoints: DashboardEntry[]; }; function ensureSerializable(obj: T): T { try { return JSON.parse(JSON.stringify(obj)) as T; } catch (error) { throw new Error(`Object contains non-serializable values: ${error}`); } } export const Route = createFileRoute('/')({ loader: async () => { 'use server'; const { agent, runtime } = await import('@/lib/agent'); // Get manifest to extract schemas const manifest = runtime.manifest.build('http://localhost'); const manifestEntrypoints = manifest.entrypoints || {}; const rawEntrypoints = agent.listEntrypoints(); const entrypoints: DashboardEntry[] = rawEntrypoints.map( (entry: { key: string; description?: string; stream?: boolean; price?: any; network?: string; }) => { // Find corresponding manifest entry for schema info const manifestEntry = manifestEntrypoints[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_schema || null, outputSchema: manifestEntry?.output_schema || null, }; } ); const configPayments = runtime.payments?.config; const payments: AgentPayments | null = 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; const result: DashboardData = { meta, payments, entrypoints }; return ensureSerializable(result); }, component: HomePage, }); const DEFAULT_PAYLOAD = JSON.stringify({ input: {} }, null, 2); const MANIFEST_PATH = '/.well-known/agent-card.json'; type HealthState = 'loading' | 'healthy' | 'error'; type ManifestState = 'idle' | 'loading' | 'loaded' | 'error'; const EntryPriceSchema = (price: DashboardEntry['price']) => { if (!price) return undefined; if (typeof price === 'string') return { invoke: price, stream: price }; return { invoke: price.invoke ?? undefined, stream: price.stream ?? undefined, }; }; const derivePriceLabel = ( entrypoint: DashboardEntry, payments?: AgentPayments | null ) => { const breakdown = EntryPriceSchema(entrypoint.price); const defaultPrice = payments?.defaultPrice ?? undefined; const invokePrice = breakdown?.invoke ?? defaultPrice; const streamPrice = entrypoint.streaming ? (breakdown?.stream ?? defaultPrice) : (breakdown?.stream ?? undefined); if (!invokePrice && !streamPrice) { return 'Free'; } if (invokePrice && streamPrice && invokePrice !== streamPrice) { return `Invoke: ${invokePrice} · Stream: ${streamPrice}`; } if (invokePrice && !streamPrice) { return `Invoke: ${invokePrice}`; } if (streamPrice && !invokePrice) { return `Stream: ${streamPrice}`; } return `Invoke · Stream: ${invokePrice ?? streamPrice}`; }; type EntrypointCard = { key: string; description: string; streaming: boolean; priceLabel: string; networkId?: string | null; invokePath: string; streamPath?: string; invokeCurl: string; streamCurl?: string; requiresPayment: boolean; inputSchema?: Record | null; outputSchema?: Record | null; }; const indentPayload = (payload: string) => payload .split('\n') .map((line, index) => (index === 0 ? line : ` ${line}`)) .join('\n'); const buildEntrypointCards = ( origin: string, entrypoints: DashboardEntry[], payments?: AgentPayments | null ): EntrypointCard[] => { const payloadIndented = indentPayload(DEFAULT_PAYLOAD); return entrypoints?.map(entrypoint => { const streaming = Boolean(entrypoint.streaming); const invokePath = `/api/agent/entrypoints/${entrypoint.key}/invoke`; const streamPath = streaming ? `/api/agent/entrypoints/${entrypoint.key}/stream` : undefined; const priceLabel = derivePriceLabel(entrypoint, payments); const requiresPayment = priceLabel !== 'Free'; const invokeCurl = [ 'curl -s -X POST \\', ` '${origin}${invokePath}' \\`, " -H 'Content-Type: application/json' \\", " -d '", payloadIndented, " '", ].join('\n'); const streamCurl = streamPath ? [ 'curl -sN -X POST \\', ` '${origin}${streamPath}' \\`, " -H 'Content-Type: application/json' \\", " -H 'Accept: text/event-stream' \\", " -d '", payloadIndented, " '", ].join('\n') : undefined; return { key: entrypoint.key, description: entrypoint.description ?? 'No description provided.', streaming, priceLabel, networkId: entrypoint.network ?? payments?.network ?? null, invokePath, streamPath, invokeCurl, streamCurl, requiresPayment, inputSchema: entrypoint.inputSchema, outputSchema: entrypoint.outputSchema, }; }); }; const StatusChip = ({ state }: { state: HealthState }) => { const config = { healthy: { label: 'Healthy', icon: '✓', className: 'border-emerald-500/50 bg-emerald-500/10 text-emerald-400', }, loading: { label: 'Checking', icon: '●', className: 'border-amber-500/50 bg-amber-500/10 text-amber-400 animate-pulse', }, error: { label: 'Error', icon: '✕', className: 'border-rose-500/50 bg-rose-500/10 text-rose-400', }, }; const { label, icon, className } = config[state]; return ( {icon} {label} ); }; const formatResult = (value: unknown) => { if (typeof value === 'string') return value; if (!value) return 'No response body'; try { return JSON.stringify(value, null, 2); } catch (error) { return String(value); } }; function useCopyFeedback() { const [flag, setFlag] = useState(false); const copyValue = useCallback(async (value?: string) => { if (!value) return; try { if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) { await navigator.clipboard.writeText(value); } else if (typeof document !== 'undefined') { const textarea = document.createElement('textarea'); textarea.value = value; textarea.setAttribute('readonly', 'readonly'); textarea.style.position = 'absolute'; textarea.style.left = '-9999px'; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); } setFlag(true); setTimeout(() => setFlag(false), 2_000); } catch (error) { // Silently fail - user can manually copy if needed } }, []); return { copyValue, flag }; } type InvocationState = { payload: string; error: string | null; result: unknown; paymentUsed: boolean; streamingEvents: string[]; streamingError: string | null; streamingStatus: 'idle' | 'streaming' | 'error'; }; const defaultInvocationState = (): InvocationState => ({ payload: DEFAULT_PAYLOAD, error: null, result: null, paymentUsed: false, streamingEvents: [], streamingError: null, streamingStatus: 'idle', }); function HomePage() { const dashboard = Route.useLoaderData() as DashboardData; const entrypoints = dashboard.entrypoints; const payments = dashboard.payments; const meta = dashboard.meta; const { data: walletClient } = useWalletClient(); const origin = typeof window !== 'undefined' ? window.location.origin : 'http://localhost'; const cards = useMemo( () => buildEntrypointCards(origin, entrypoints, payments), [origin, entrypoints, payments] ); const entrypointCount = cards?.length ?? 0; const entrypointLabel = entrypointCount === 1 ? 'Entrypoint' : 'Entrypoints'; const [healthState, setHealthState] = useState('loading'); const [healthData, setHealthData] = useState(null); const [manifestState, setManifestState] = useState('idle'); const [manifestText, setManifestText] = useState( 'Manifest unavailable.' ); const [invocationStates, setInvocationStates] = useState< Record >({}); const streamCancelRef = useRef void>>({}); const getEntryState = useCallback( (key: string) => invocationStates[key] ?? defaultInvocationState(), [invocationStates] ); const updateEntryState = useCallback( ( key: string, updates: | Partial | ((prev: InvocationState) => InvocationState) ) => { setInvocationStates(prev => { const base = prev[key] ?? defaultInvocationState(); const next = typeof updates === 'function' ? updates(base) : { ...base, ...updates }; return { ...prev, [key]: next, }; }); }, [] ); useEffect(() => { let cancelled = false; const fetchHealth = async () => { try { const health = await getHealth(); if (cancelled) return; setHealthData(health); const ok = health.ok === true || (health.status && health.status.toLowerCase().includes('ok')) || (health.status && health.status.toLowerCase().includes('healthy')); setHealthState(ok ? 'healthy' : 'error'); } catch (error) { if (!cancelled) { setHealthState('error'); } } }; fetchHealth(); const interval = setInterval(fetchHealth, 30_000); return () => { cancelled = true; clearInterval(interval); }; }, []); useEffect(() => { let cancelled = false; const fetchManifest = async () => { setManifestState('loading'); try { const manifest = await getManifest(); if (cancelled) return; const text = manifest && typeof manifest === 'object' ? JSON.stringify(manifest, null, 2) : typeof manifest === 'string' ? manifest : 'Manifest unavailable.'; setManifestText(text); setManifestState('loaded'); } catch (error) { if (!cancelled) { setManifestText('Failed to load manifest.'); setManifestState('error'); } } }; fetchManifest(); return () => { cancelled = true; }; }, []); const { copyValue: copyCurl, flag: curlCopied } = useCopyFeedback(); const { copyValue: copyManifest, flag: manifestCopied } = useCopyFeedback(); const { copyValue: copyAppKitSnippet, flag: appKitSnippetCopied } = useCopyFeedback(); const handleInvoke = useCallback( async (entry: EntrypointCard, payloadInput: string) => { let parsedBody: unknown = {}; try { parsedBody = payloadInput.trim() ? JSON.parse(payloadInput) : {}; updateEntryState(entry.key, { error: null }); } catch (error) { updateEntryState(entry.key, { error: 'Payload must be valid JSON' }); return; } let signer: unknown = undefined; let paymentUsed = false; if (entry.requiresPayment) { try { getNetworkInfo(entry.networkId ?? payments?.network ?? undefined); if (walletClient) { signer = walletClient; paymentUsed = true; } } catch { // Payment signer unavailable - continue without payment } } try { const result = await invokeEntrypointWithBody({ key: entry.key, body: parsedBody, signer, }); updateEntryState(entry.key, { result, paymentUsed, }); } catch (error) { updateEntryState(entry.key, { error: (error as Error).message, paymentUsed: false, }); } }, [payments?.network, updateEntryState, walletClient] ); const handleStream = useCallback( async (entry: EntrypointCard, payloadInput: string) => { streamCancelRef.current[entry.key]?.(); updateEntryState(entry.key, { streamingEvents: [], streamingError: null, streamingStatus: 'streaming', }); let parsedBody: unknown = {}; try { parsedBody = payloadInput.trim() ? JSON.parse(payloadInput) : {}; } catch { updateEntryState(entry.key, { streamingStatus: 'error', streamingError: 'Payload must be valid JSON', }); return; } let signer: unknown = undefined; if (entry.requiresPayment) { try { getNetworkInfo(entry.networkId ?? payments?.network ?? undefined); if (walletClient) { signer = walletClient; // Streaming does not mark payment used up-front; chunk handlers show success. } } catch { // Payment signer unavailable - continue without payment } } try { const { cancel } = await streamEntrypointWithBody({ key: entry.key, body: parsedBody, signer, onChunk: chunk => { if (chunk && typeof chunk === 'object' && 'kind' in chunk) { if ((chunk as any).kind === 'text') { updateEntryState(entry.key, prev => ({ ...prev, streamingEvents: [ ...prev.streamingEvents, String((chunk as any).text ?? ''), ], })); } if ((chunk as any).kind === 'run-end') { updateEntryState(entry.key, { streamingStatus: 'idle' }); } } }, onError: error => { updateEntryState(entry.key, { streamingStatus: 'error', streamingError: error.message, }); }, onDone: () => { updateEntryState(entry.key, { streamingStatus: 'idle', }); }, }); streamCancelRef.current[entry.key] = cancel; } catch (error) { updateEntryState(entry.key, { streamingStatus: 'error', streamingError: (error as Error).message, }); } }, [payments?.network, updateEntryState, walletClient] ); useEffect(() => { return () => { Object.values(streamCancelRef.current).forEach(cancel => cancel?.()); }; }, []); const networkInfo = getNetworkInfo(payments?.network ?? undefined); const appKitSnippet = [ 'import { useWalletClient } from "wagmi";', 'import { wrapFetchWithPayment } from "x402-fetch";', '', 'const { data: walletClient } = useWalletClient();', '', 'if (walletClient) {', ' const fetchWithPayment = wrapFetchWithPayment(fetch, walletClient);', ' // await fetchWithPayment(...)', '}', '', '// Ensure WALLET_CONNECT_PROJECT_ID is configured to use WalletConnect.', ].join('\n'); return (
🤖

{meta?.name ?? 'Lucid Agent'}

v{meta?.version ?? '0.0.0'}

{meta?.description ?? 'Monitor agent health, review entrypoints, and interact with invoke and streaming flows.'}

💚

Health

Status
{healthData?.status ?? (healthState === 'healthy' ? 'ok' : 'unknown')}
Last Checked
{healthData?.timestamp ?? 'Just now'}
📊

Configuration

Entrypoints
{entrypointCount}
Network
{networkInfo.label}
Default Price
{payments?.defaultPrice ?? 'Free'}
💰

Payment

Recipient
{payments?.payTo ?? '—'}

{entrypointCount} {entrypointLabel}

Configure payloads and test your agent endpoints

{cards?.map(card => { const state = getEntryState(card.key); return (

{card.key}

{card.streaming ? 'Stream' : 'Invoke'}

{card.description}

Pricing {card.priceLabel}
Network { getNetworkInfo( card.networkId ?? payments?.network ?? undefined ).label }
Invoke Path {card.invokePath}
{card.streamPath && (
Stream Path {card.streamPath}
)}
updateEntryState(card.key, { payload: value }) } /> {card.outputSchema && card.outputSchema.properties && (
Expected Output Schema
{Object.entries(card.outputSchema.properties).map( ([name, schema]: [string, any]) => (
{name}:
{schema.type} {schema.description && ` - ${schema.description}`}
) )}
)} {state.error && (

{state.error}

)}
{card.streaming && ( )} {card.streaming && state.streamingStatus === 'streaming' && ( )}
Response {Boolean(state.result) && ( )}
{state.paymentUsed && ( 💰 Paid )}
                      {formatResult(state.result) || (
                        
                          Click "Invoke" to see the response here...
                        
                      )}
                    
{card.streaming && (
Stream Events {state.streamingStatus === 'streaming' && ( )}
{state.streamingStatus === 'streaming' ? '● Live' : '○ Idle'}
{state.streamingEvents.length === 0 ? (

Click "Start Stream" to see live events here...

) : (
    {state.streamingEvents.map((event, index) => (
  • {event}
  • ))}
)}
{state.streamingStatus === 'error' && state.streamingError && (

{state.streamingError}

)}
)}
); })}
📄

Agent Manifest

Complete agent specification served from{' '} {MANIFEST_PATH}

View Full Manifest JSON {manifestState === 'loading' && (
)}
                {manifestState === 'loading' ? (
                  
Loading manifest…
) : ( manifestText )}
💻

Code Examples

Integration snippets for your applications

WalletConnect AppKit
                {appKitSnippet}
              
); }