This commit is contained in:
seb
2026-10-06 11:49:10 +02:00
parent 4769a87c54
commit cbf669f640
6 changed files with 384 additions and 563 deletions

View File

@@ -23,8 +23,7 @@ import EscalatorWarningIcon from '@mui/icons-material/EscalatorWarning';
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
import ManageSearchIcon from '@mui/icons-material/ManageSearch';
import HealingMarkdown from './HealingMarkdown';
import { ChatMessageAttachments } from './ChatAttachmentItems';
import ChatAttachmentPreviewModal from './ChatAttachmentPreviewModal';
import { VfsAttachmentLink, parseAttachmentsFromText } from './ChatAttachmentItems';
import {
CHROMA,
SHADOW_BUBBLE_ASSISTANT,
@@ -727,30 +726,13 @@ export function normalizeChatMessages(rawMessages = []) {
}
const payload = parseMessagePayload(msg.message);
let attachments = Array.isArray(msg.attachments) ? [...msg.attachments] : [];
if (attachments.length === 0 && Array.isArray(payload.attachments)) {
attachments = [...payload.attachments];
}
let userText = payload.content !== undefined ? payload.content : msg.message;
if (typeof userText === 'string' && userText.startsWith('{')) {
try {
const nested = JSON.parse(userText);
if (nested && typeof nested === 'object') {
if (nested.content !== undefined) userText = nested.content;
if (Array.isArray(nested.attachments) && attachments.length === 0) {
attachments = [...nested.attachments];
}
}
} catch {}
}
const userText = payload.content !== undefined ? payload.content : msg.message;
if (msg.role === 'user') {
flushAssistant();
result.push({
...msg,
message: userText,
attachments,
});
continue;
}
@@ -846,7 +828,7 @@ export function normalizeChatMessages(rawMessages = []) {
return result;
}
function MessageRow({ msg, showTime = true, onPreviewAttachment }) {
function MessageRow({ msg, showTime = true }) {
// If the message has structured turns, render each turn
if (msg.turns && Array.isArray(msg.turns) && msg.turns.length > 0) {
return (
@@ -860,22 +842,17 @@ function MessageRow({ msg, showTime = true, onPreviewAttachment }) {
const payload = parseMessagePayload(msg.message);
let textContent = payload.content !== undefined ? payload.content : msg.message;
let attachments = Array.isArray(msg.attachments) ? msg.attachments : [];
if (attachments.length === 0 && Array.isArray(payload.attachments)) {
attachments = payload.attachments;
}
if (typeof textContent === 'string' && textContent.startsWith('{')) {
try {
const nested = JSON.parse(textContent);
if (nested && typeof nested === 'object') {
if (nested.content !== undefined) textContent = nested.content;
if (Array.isArray(nested.attachments) && attachments.length === 0) {
attachments = nested.attachments;
}
if (nested && typeof nested === 'object' && nested.content !== undefined) {
textContent = nested.content;
}
} catch {}
}
const { attachments: vfsAttachments, cleanText } = parseAttachmentsFromText(textContent);
if (msg.role === 'system') {
return (
<Box sx={{ display: 'flex', justifyContent: 'center', py: 0.75, px: 2 }}>
@@ -952,19 +929,32 @@ function MessageRow({ msg, showTime = true, onPreviewAttachment }) {
lineHeight: 1.5,
})}
>
{attachments && attachments.length > 0 && (
<ChatMessageAttachments
attachments={attachments}
isUser={isUser}
onPreview={onPreviewAttachment}
/>
{vfsAttachments.length > 0 && (
<Box
sx={{
display: 'flex',
flexWrap: 'wrap',
gap: 0.75,
mb: cleanText ? 0.75 : 0,
}}
>
{vfsAttachments.map((att, idx) => (
<VfsAttachmentLink
key={att.path || idx}
name={att.name}
path={att.path}
type={att.type}
isUser={isUser}
/>
))}
</Box>
)}
{textContent ? (
{cleanText ? (
isUser ? (
textContent
cleanText
) : (
<HealingMarkdown text={textContent} streaming={msg.streaming} />
<HealingMarkdown text={cleanText} streaming={msg.streaming} />
)
) : null}
</Box>
@@ -978,18 +968,6 @@ export default class ChatFlowList extends PureComponent {
bottomRef = createRef();
scrollTimeout = null;
state = {
previewAttachment: null,
};
handlePreviewAttachment = (attachment) => {
this.setState({ previewAttachment: attachment });
};
handleClosePreview = () => {
this.setState({ previewAttachment: null });
};
componentDidMount() {
this.scrollToBottom('auto');
}
@@ -1031,7 +1009,6 @@ export default class ChatFlowList extends PureComponent {
render() {
const { messages = [], activeTurns = [] } = this.props;
const { previewAttachment } = this.state;
const normalizedMessages = normalizeChatMessages(messages);
if (normalizedMessages.length === 0 && activeTurns.length === 0) {
@@ -1065,7 +1042,6 @@ export default class ChatFlowList extends PureComponent {
key={msg.id || index}
msg={msg}
showTime={showTime}
onPreviewAttachment={this.handlePreviewAttachment}
/>
);
})}
@@ -1078,12 +1054,6 @@ export default class ChatFlowList extends PureComponent {
: null}
<div ref={this.bottomRef} style={{ height: 1, flexShrink: 0 }} />
<ChatAttachmentPreviewModal
open={Boolean(previewAttachment)}
attachment={previewAttachment}
onClose={this.handleClosePreview}
/>
</Box>
);
}