add reasoning block
This commit is contained in:
@@ -44,10 +44,12 @@ import AssistantMessageActions from './AssistantMessageActions'
|
||||
import PromptInputWithActions, { ChatUserInputRef } from './chat-input/PromptInputWithActions'
|
||||
import { editorStateToPlainText } from './chat-input/utils/editor-state-to-plain-text'
|
||||
import { ChatHistory } from './ChatHistory'
|
||||
import MarkdownReasoningBlock from './MarkdownReasoningBlock'
|
||||
import QueryProgress, { QueryProgressState } from './QueryProgress'
|
||||
import ReactMarkdown from './ReactMarkdown'
|
||||
import ShortcutInfo from './ShortcutInfo'
|
||||
import SimilaritySearchResults from './SimilaritySearchResults'
|
||||
|
||||
// Add an empty line here
|
||||
const getNewInputMessage = (app: App): ChatUserMessage => {
|
||||
return {
|
||||
@@ -242,6 +244,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
{
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
reasoningContent: '',
|
||||
id: responseMessageId,
|
||||
metadata: {
|
||||
usage: undefined,
|
||||
@@ -269,6 +272,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
{
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
reasoningContent: '',
|
||||
id: responseMessageId,
|
||||
metadata: {
|
||||
usage: undefined,
|
||||
@@ -290,12 +294,14 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
|
||||
for await (const chunk of stream) {
|
||||
const content = chunk.choices[0]?.delta?.content ?? ''
|
||||
const reasoning_content = chunk.choices[0]?.delta?.reasoning_content ?? ''
|
||||
setChatMessages((prevChatHistory) =>
|
||||
prevChatHistory.map((message) =>
|
||||
message.role === 'assistant' && message.id === responseMessageId
|
||||
? {
|
||||
...message,
|
||||
content: message.content + content,
|
||||
reasoningContent: message.reasoningContent + reasoning_content,
|
||||
metadata: {
|
||||
...message.metadata,
|
||||
usage: chunk.usage ?? message.metadata?.usage, // Keep existing usage if chunk has no usage data
|
||||
@@ -584,13 +590,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
{
|
||||
// If the chat is empty, show a message to start a new chat
|
||||
chatMessages.length === 0 && (
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
}}>
|
||||
<div className="infio-chat-empty-state">
|
||||
<ShortcutInfo />
|
||||
</div>
|
||||
)
|
||||
@@ -638,6 +638,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
</div>
|
||||
) : (
|
||||
<div key={message.id} className="infio-chat-messages-assistant">
|
||||
<MarkdownReasoningBlock reasoningContent={message.reasoningContent} />
|
||||
<ReactMarkdownItem
|
||||
handleApply={handleApply}
|
||||
isApplying={applyMutation.isPending}
|
||||
|
||||
56
src/components/chat-view/MarkdownReasoningBlock.tsx
Normal file
56
src/components/chat-view/MarkdownReasoningBlock.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { ChevronDown, ChevronRight } from 'lucide-react'
|
||||
import { PropsWithChildren, useEffect, useRef, useState } from 'react'
|
||||
|
||||
import { useDarkModeContext } from '../../contexts/DarkModeContext'
|
||||
|
||||
import { MemoizedSyntaxHighlighterWrapper } from './SyntaxHighlighterWrapper'
|
||||
|
||||
export default function MarkdownReasoningBlock({
|
||||
reasoningContent,
|
||||
}: PropsWithChildren<{
|
||||
reasoningContent: string
|
||||
}>) {
|
||||
const { isDarkMode } = useDarkModeContext()
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current) {
|
||||
containerRef.current.scrollTop = containerRef.current.scrollHeight
|
||||
}
|
||||
}, [reasoningContent])
|
||||
|
||||
return (
|
||||
reasoningContent && (
|
||||
<div
|
||||
className={`infio-chat-code-block has-filename infio-reasoning-block`}
|
||||
>
|
||||
<div className={'infio-chat-code-block-header'}>
|
||||
<div className={'infio-chat-code-block-header-filename'}>
|
||||
Reasoning
|
||||
</div>
|
||||
<button
|
||||
className="clickable-icon infio-chat-list-dropdown"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
{isOpen ? <ChevronDown size={16} /> : <ChevronRight size={16} />}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="infio-reasoning-content-wrapper"
|
||||
>
|
||||
<MemoizedSyntaxHighlighterWrapper
|
||||
isDarkMode={isDarkMode}
|
||||
language="markdown"
|
||||
hasFilename={true}
|
||||
wrapLines={true}
|
||||
isOpen={isOpen}
|
||||
>
|
||||
{reasoningContent}
|
||||
</MemoizedSyntaxHighlighterWrapper>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -11,13 +11,17 @@ function SyntaxHighlighterWrapper({
|
||||
hasFilename,
|
||||
wrapLines,
|
||||
children,
|
||||
isOpen = true,
|
||||
}: {
|
||||
isDarkMode: boolean
|
||||
language: string | undefined
|
||||
hasFilename: boolean
|
||||
wrapLines: boolean
|
||||
children: string
|
||||
isOpen?: boolean
|
||||
}) {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<SyntaxHighlighter
|
||||
language={language}
|
||||
|
||||
Reference in New Issue
Block a user