73 lines
1.9 KiB
TypeScript
73 lines
1.9 KiB
TypeScript
import React from 'react'
|
|
import { cn } from '@/utils/cn'
|
|
import type { MessageContent, UserInteraction, BaseEvent } from '../../types'
|
|
import { MarkdownContent } from '../../task-panel/Preview/MarkdownPreview'
|
|
import { UserInteractionWidget } from './user-interaction'
|
|
|
|
export interface ContentMessageProps {
|
|
content?: MessageContent
|
|
userInteraction?: UserInteraction
|
|
base?: BaseEvent
|
|
isUserInput: boolean
|
|
showUserFile: boolean
|
|
onSendMessage?: (content: string) => void
|
|
}
|
|
|
|
/**
|
|
* 内容消息组件 - 渲染文本内容与用户交互,对应 next-agent ContentMessage/FactCheck
|
|
*/
|
|
function InnerContentMessage({
|
|
content,
|
|
userInteraction,
|
|
isUserInput,
|
|
showUserFile,
|
|
onSendMessage,
|
|
}: ContentMessageProps) {
|
|
const text = content?.content || content?.text
|
|
|
|
if (!text && !userInteraction) return null
|
|
|
|
return (
|
|
<div
|
|
className={cn('flex flex-col w-full', {
|
|
'items-end': isUserInput,
|
|
'items-start': !isUserInput,
|
|
'mt-9 mb-0 px-3': showUserFile,
|
|
'my-9': isUserInput && !showUserFile,
|
|
})}
|
|
>
|
|
{text && (
|
|
<div
|
|
className={cn(
|
|
'max-w-[80%]',
|
|
isUserInput
|
|
? 'bg-gray-900 text-white rounded-2xl rounded-tr-sm'
|
|
: 'text-gray-900',
|
|
)}
|
|
>
|
|
{isUserInput ? (
|
|
<div className="whitespace-pre-wrap py-3 px-4 break-words leading-relaxed text-sm">
|
|
{text}
|
|
</div>
|
|
) : (
|
|
<MarkdownContent content={text} className="[&_p]:mt-0" />
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{userInteraction && (
|
|
<div className="w-full max-w-[80%]">
|
|
<UserInteractionWidget
|
|
userInteraction={userInteraction}
|
|
disabled={false}
|
|
onSendMessage={onSendMessage}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export const ContentMessage = React.memo(InnerContentMessage)
|
|
export default ContentMessage
|