(
String(index)}
error={events.error ? String(events.error) : null}
splitLayoutStorageKey="sse_events"
defaultRatio={0.4}
renderRow={({ event, index, isActive, onClick }) => (
}
content={
{getEventPreview(event, summarySettings.resultKeyPath, filterEventPreviews)}
}
/>
)}
renderDetail={({ event, index, onClose }) => (
)}
/>
)}
secondSlot={
showExtractedText
? ({ style }) => (
)
: null
}
/>
);
}
function SseSummaryFooter({
error,
fragmentCount,
isLoading,
onRenderMarkdownChange,
renderMarkdown,
resultKeyPath,
style,
summary,
}: {
error: string | null;
fragmentCount: number;
isLoading: boolean;
onRenderMarkdownChange: (renderMarkdown: boolean) => void;
renderMarkdown: boolean;
resultKeyPath: string;
style: CSSProperties;
summary: string;
}) {
const hasSummary = fragmentCount > 0;
const actions = useMemo(
() => [
{
key: "sse-summary-format",
label: "Extracted text format",
type: "select" as const,
value: renderMarkdown ? "markdown" : "text",
options: [
{ label: "Text", value: "text" },
{ label: "Markdown", value: "markdown" },
],
onChange: (value: string) => onRenderMarkdownChange(value === "markdown"),
},
],
[onRenderMarkdownChange, renderMarkdown],
);
return (
{error != null ? (
{error}
) : isLoading ? (
Loading extracted text...
) : hasSummary ? (
renderMarkdown ? (
{summary}
) : (
{summary}
)
) : (
No fragments for {resultKeyPath}
)}
);
}
function getEventPreview(
event: ServerSentEvent,
resultKeyPath: string | null,
filterEventPreview: boolean,
): string {
if (filterEventPreview && resultKeyPath != null) {
return (extractSseValueAtPath(event.data, resultKeyPath) ?? event.data).slice(0, 1000);
}
return event.data.slice(0, 1000);
}
function EventDetail({
applyJsonPath,
event,
index,
resultKeyPath,
showLarge,
showingLarge,
setShowLarge,
setShowingLarge,
onClose,
}: {
applyJsonPath: boolean;
event: ServerSentEvent;
index: number;
resultKeyPath: string | null;
showLarge: boolean;
showingLarge: boolean;
setShowLarge: (v: boolean) => void;
setShowingLarge: (v: boolean) => void;
onClose: () => void;
}) {
const detailText = useMemo(
() =>
applyJsonPath && resultKeyPath != null
? (extractSseValueAtPath(event.data, resultKeyPath) ?? event.data)
: event.data,
[applyJsonPath, event.data, resultKeyPath],
);
const language = useMemo<"text" | "json">(() => {
if (!detailText) return "text";
return isJSON(detailText) ? "json" : "text";
}, [detailText]);
return (
}
onClose={onClose}
/>
{!showLarge && detailText.length > 1000 * 1000 ? (
Message previews larger than 1MB are hidden
) : (
)}
);
}
function FormattedEditor({ text, language }: { text: string; language: EditorProps["language"] }) {
const formatted = useFormatText({ text, language, pretty: true });
if (formatted == null) return null;
return ;
}
function EventLabels({
className,
event,
index,
isActive,
}: {
event: ServerSentEvent;
index: number;
className?: string;
isActive?: boolean;
}) {
return (
{event.id ?? index}
{event.eventType && {event.eventType}}
);
}
function EventLabel({ children, isActive }: { children: ReactNode; isActive?: boolean }) {
return (
{isActive && }
{children}
);
}