ResponseView
Die Antwort eines Modells, während sie einläuft: Markdown mit leisem Cursor, Reasoning in einem „Denkt nach“-Bereich und ruhige Zustände für Abbruch und Fehler.
Subject: Your order #4471 is on its way — and we’re sorry it’s late
Hi Maya,
Your order #4471 left our warehouse on time, but a delay with our carrier held it up for three days. That’s not the experience we want for you, and I’m sorry.
It’s moving again and should arrive by Thursday. As a thank-you for your patience, your next order ships free — the code is applied to your account automatically.
Warmly,
The Northwind team
- Erstes Token
- 1,18 s
- Gesamt
- 6,12 s
function Stream() {
const [state, setState] = useState<{ status: ResponseStatus; text: string; reasoning: string; took?: number; started?: number; total?: number }>({
status: "done",
text: gpt.text,
reasoning: gpt.reasoning!,
took: 3800,
total: 6120,
});
const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
useEffect(() => () => clearTimeout(timer.current), []);
const play = () => {
clearTimeout(timer.current);
const started = Date.now();
let r = 0;
let t = 0;
let took: number | undefined;
setState({ status: "pending", text: "", reasoning: "", started });
const tick = () => {
if (r < gpt.reasoning!.length) r += 8;
else {
took ??= Date.now() - started;
t += 6;
}
const done = t >= gpt.text.length;
setState({
status: done ? "done" : "streaming",
reasoning: gpt.reasoning!.slice(0, r),
text: gpt.text.slice(0, t),
started,
...(took !== undefined ? { took } : {}),
...(done ? { total: Date.now() - started } : {}),
});
if (!done) timer.current = setTimeout(tick, 24);
};
timer.current = setTimeout(tick, 700);
};
return (
<div className="flex w-full max-w-560 flex-col gap-16">
<div>
<Button size="sm" onClick={play} disabled={state.status === "pending" || state.status === "streaming"}>
Stream it again
</Button>
</div>
<ResponseView
aria-label="GPT-5 response"
status={state.status}
text={state.text}
reasoning={state.reasoning}
{...(state.took !== undefined ? { reasoningDuration: state.took } : {})}
footer={
<ResponseMetrics
reasoning
live={state.status === "pending" || state.status === "streaming"}
startedAt={state.started}
duration={state.total}
timeToFirstToken={state.status === "pending" ? undefined : 1180}
/>
}
/>
</div>
);
}import { ResponseView, UserMessage, Thread } from "@logicplanes/kaeso-ui/playground";Props
aria-labelstringDer zugängliche Name der Antwort („GPT-5-Antwort“ in einem Vergleich). Standardmäßig „Antwort“ in der Sprache des LocaleProvider.
defaultReasoningOpenbooleanOb das Reasoning zu Beginn ausgeklappt ist.
footerReactNodeUnter der Antwort: ihre Kennzahlen, Aktionen.
onReasoningOpenChange((open: boolean) => void)Wird aufgerufen, wenn das Reasoning aus- oder eingeklappt wird.
onRetry(() => void)Sendet den Durchgang erneut; erscheint bei einem Fehler oder Abbruch.
reasoningstringDie bisherige Reasoning-Zusammenfassung als Markdown. Ein „Denkt nach“-Bereich zeigt sie, standardmäßig zugeklappt.
reasoningDurationnumberWie lange das Modell nachgedacht hat, in Millisekunden: „4,2 s nachgedacht“.
reasoningOpenbooleanOb das Reasoning ausgeklappt ist, bei gesteuertem Zustand.
status"done" | "error" | "streaming" | "pending" | "stopped" = doneWo die Antwort steht: wartend, streamend, fertig, gestoppt oder fehlgeschlagen.
textstringDer bisherige Ausgabetext als Markdown.