Add blinking cursor to active streaming text
This commit is contained in:
@@ -546,7 +546,7 @@ const MessageBubble = React.memo(function MessageBubble({
|
||||
}}
|
||||
>
|
||||
{!isUser && msg.timeline && msg.timeline.length > 0 && (
|
||||
<Timeline entries={msg.timeline} />
|
||||
<Timeline entries={msg.timeline} isActiveStream={sending && msgIndex === messages.length - 1} />
|
||||
)}
|
||||
{/*
|
||||
Render the legacy bottom content bubble ONLY when:
|
||||
@@ -600,7 +600,7 @@ const MessageBubble = React.memo(function MessageBubble({
|
||||
* name with a ×N counter. The flow visually mirrors what actually
|
||||
* happened: thought → tools → thought → tools → ... → final summary.
|
||||
*/
|
||||
function Timeline({ entries }: { entries: TimelineEntry[] }) {
|
||||
function Timeline({ entries, isActiveStream }: { entries: TimelineEntry[], isActiveStream?: boolean }) {
|
||||
// Walk the entries and emit a renderable list. Adjacent same-category
|
||||
// tool entries get bundled into a TimelineToolGroup; thought and
|
||||
// text entries pass through as-is.
|
||||
@@ -634,11 +634,12 @@ function Timeline({ entries }: { entries: TimelineEntry[] }) {
|
||||
return (
|
||||
<div style={{ marginBottom: 6 }}>
|
||||
{items.map((item, i) => {
|
||||
const isLast = i === items.length - 1;
|
||||
if (item.kind === "thought") {
|
||||
return <TimelineText key={i} text={item.text} />;
|
||||
return <TimelineText key={i} text={item.text} isStreaming={isActiveStream && isLast} />;
|
||||
}
|
||||
if (item.kind === "text") {
|
||||
return <TimelineText key={i} text={item.text} />;
|
||||
return <TimelineText key={i} text={item.text} isStreaming={isActiveStream && isLast} />;
|
||||
}
|
||||
if (item.kind === "toolGroup") {
|
||||
return (
|
||||
@@ -660,7 +661,7 @@ function Timeline({ entries }: { entries: TimelineEntry[] }) {
|
||||
* bubble so each round of multi-tool-loop output reads as a discrete
|
||||
* step instead of concatenating into a wall of text.
|
||||
*/
|
||||
function TimelineText({ text }: { text: string }) {
|
||||
function TimelineText({ text, isStreaming }: { text: string; isStreaming?: boolean }) {
|
||||
const proseWrap: React.CSSProperties = {
|
||||
overflowWrap: "anywhere",
|
||||
wordBreak: "break-word",
|
||||
@@ -684,7 +685,7 @@ function TimelineText({ text }: { text: string }) {
|
||||
<span
|
||||
style={proseWrap}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: renderMarkdown(stripRawToolLogs(text)),
|
||||
__html: renderMarkdown(stripRawToolLogs(text)) + (isStreaming ? `<span class="animate-pulse" style="display:inline-block; width:6px; height:13px; background-color:#9ca3af; vertical-align:-1px; margin-left:2px; border-radius:1px;"></span>` : ""),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user