fix: keep streamed reasoning visible

This commit is contained in:
lofyer
2026-08-14 09:55:07 +08:00
parent 7a86c96623
commit fca9888f83
2 changed files with 75 additions and 30 deletions
+30
View File
@@ -1325,6 +1325,36 @@ describe('App', () => {
.closest('details')
expect(streamingReasoning).toHaveAttribute('open')
expect(screen.getByText('先检查项目结构')).toBeInTheDocument()
const reasoningContent =
streamingReasoning!.querySelector<HTMLElement>(
'.message-reasoning__content'
)
if (!reasoningContent) {
throw new Error('Missing reasoning content')
}
const reasoningScrollTo = vi.fn()
reasoningContent.scrollTo = reasoningScrollTo
Object.defineProperty(reasoningContent, 'scrollHeight', {
configurable: true,
value: 640
})
act(() => {
if (!request) {
throw new Error('Missing request')
}
agentListener?.({
requestId: request.requestId,
type: 'reasoning',
delta: ',再确认依赖'
})
})
expect(reasoningScrollTo).toHaveBeenLastCalledWith({
top: 640,
behavior: 'auto'
})
expect(screen.getByText('先检查项目结构,再确认依赖')).toBeInTheDocument()
act(() => {
if (!request) {
+45 -30
View File
@@ -524,6 +524,43 @@ function groupMessageBlocks(
return items
}
function MessageReasoning({
content,
streaming
}: {
content: string
streaming: boolean
}): React.JSX.Element {
const { t } = useTranslation('app')
const contentRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!streaming || !contentRef.current) {
return
}
contentRef.current.scrollTo({
top: contentRef.current.scrollHeight,
behavior: 'auto'
})
}, [content, streaming])
return (
<details className="message-reasoning" open={streaming}>
<summary>
{streaming
? t('chat.reasoning.streaming')
: t('chat.reasoning.complete')}
</summary>
<div
className="markdown-content message-reasoning__content"
ref={contentRef}
>
<MarkdownRenderer>{content}</MarkdownRenderer>
</div>
</details>
)
}
function ToolExecutionList({
tools
}: {
@@ -5380,22 +5417,11 @@ function App(): React.JSX.Element {
tools={item.tools}
/>
) : item.block.type === 'reasoning' ? (
<details
className="message-reasoning"
<MessageReasoning
content={item.block.content}
key={item.block.id}
open={message.state === 'streaming'}
>
<summary>
{message.state === 'streaming'
? t('chat.reasoning.streaming')
: t('chat.reasoning.complete')}
</summary>
<div className="markdown-content message-reasoning__content">
<MarkdownRenderer>
{item.block.content}
</MarkdownRenderer>
</div>
</details>
streaming={message.state === 'streaming'}
/>
) : (
<div
className="markdown-content message__content"
@@ -5411,22 +5437,11 @@ function App(): React.JSX.Element {
) : (
<>
{message.reasoning && (
<details
className="message-reasoning"
<MessageReasoning
content={message.reasoning}
key={`${message.id}-${message.state}`}
open={message.state === 'streaming'}
>
<summary>
{message.state === 'streaming'
? t('chat.reasoning.streaming')
: t('chat.reasoning.complete')}
</summary>
<div className="markdown-content message-reasoning__content">
<MarkdownRenderer>
{message.reasoning}
</MarkdownRenderer>
</div>
</details>
streaming={message.state === 'streaming'}
/>
)}
{message.content && (
<div className="markdown-content message__content">