'use client'; import { useWalletClient } from 'wagmi'; import { useCallback, useEffect, useRef, useState } from 'react'; import { invokeEntrypointWithBody, streamEntrypointWithBody, type AgentPayments, } from '@/lib/api'; import { SchemaForm } from '@/components/schema-form'; import { getNetworkInfo } from '@/lib/network'; import { cn } from '@/lib/utils'; import { useCopyFeedback } from '@/components/use-copy-feedback'; export type EntrypointCardData = { 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; defaultPayload: string; }; 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); } }; export function EntrypointCard({ card, payments, }: { card: EntrypointCardData; payments?: AgentPayments | null; }) { const { data: walletClient } = useWalletClient(); const [payload, setPayload] = useState(card.defaultPayload); const [error, setError] = useState(null); const [result, setResult] = useState(null); const [paymentUsed, setPaymentUsed] = useState(false); const [streamingStatus, setStreamingStatus] = useState< 'idle' | 'streaming' | 'error' >('idle'); const [streamingEvents, setStreamingEvents] = useState([]); const [streamingError, setStreamingError] = useState(null); const streamCancelRef = useRef<() => void>(); const { copyValue: copyCurl, copied: curlCopied } = useCopyFeedback(); const { copyValue: copyStream, copied: streamCopied } = useCopyFeedback(); const resetStream = useCallback(() => { setStreamingEvents([]); setStreamingError(null); setStreamingStatus('idle'); streamCancelRef.current?.(); }, []); const handleInvoke = useCallback(async () => { let parsedBody: unknown = {}; try { parsedBody = payload.trim() ? JSON.parse(payload) : {}; setError(null); } catch { setError('Payload must be valid JSON'); return; } let signer: unknown = undefined; let usedPayment = false; if (card.requiresPayment && walletClient) { signer = walletClient; usedPayment = true; } try { const response = await invokeEntrypointWithBody({ key: card.key, body: parsedBody, signer, }); setResult(response); setPaymentUsed(usedPayment); } catch (err) { setPaymentUsed(false); setError((err as Error).message); } }, [card.key, card.requiresPayment, payload, walletClient]); const handleStream = useCallback(async () => { resetStream(); let parsedBody: unknown = {}; try { parsedBody = payload.trim() ? JSON.parse(payload) : {}; } catch { setStreamingStatus('error'); setStreamingError('Payload must be valid JSON'); return; } let signer: unknown = undefined; if (card.requiresPayment && walletClient) { signer = walletClient; } try { const { cancel } = await streamEntrypointWithBody({ key: card.key, body: parsedBody, signer, onChunk: chunk => { if (chunk && typeof chunk === 'object' && 'kind' in chunk) { if ((chunk as any).kind === 'text') { setStreamingEvents(prev => [ ...prev, String((chunk as any).text ?? ''), ]); } if ((chunk as any).kind === 'run-end') { setStreamingStatus('idle'); } return; } setStreamingEvents(prev => [...prev, JSON.stringify(chunk)]); }, onError: err => { setStreamingStatus('error'); setStreamingError(err.message); }, onDone: () => { setStreamingStatus('idle'); }, }); streamCancelRef.current = cancel; setStreamingStatus('streaming'); } catch (err) { setStreamingStatus('error'); setStreamingError((err as Error).message); } }, [card.key, card.requiresPayment, payload, resetStream, walletClient]); useEffect(() => { return () => { streamCancelRef.current?.(); }; }, []); const networkLabel = getNetworkInfo( card.networkId ?? payments?.network ?? undefined ).label; return (

{card.key}

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

{card.description}

Pricing {card.priceLabel}
Network {networkLabel}
Invoke Path {card.invokePath}
{card.streamPath && (
Stream Path {card.streamPath}
)}
{card.outputSchema?.properties && (
Expected Output Schema
{Object.entries(card.outputSchema.properties).map( ([name, schema]) => (
{name}:
{(schema as { type?: string }).type} {(schema as { description?: string }).description ? ` - ${(schema as { description?: string }).description}` : null}
) )}
)} {error && (

{error}

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

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

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

{streamingError}

)}
)}
); }