Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 72 additions & 7 deletions web/src/embedded/chat/components/messages/assistant-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import { CueStreamdownVideo } from '../markdown/overrides/video';
import { AttachmentImage } from './attachment-image';
import { AssistantMessageOperations } from './assistant-message-operations';
import { AssistantStateSection } from './assistant-state-section';
import { FileAttachmentCard } from './file-attachment';
import {
FileAttachmentCard,
shouldRenderFileReferenceFallback,
} from './file-attachment';
import { PermissionMessage } from './permission-message';
import { QuestionMessage } from './question-message';
import { SaveFileMessage } from './save-file-message';
Expand Down Expand Up @@ -119,16 +122,30 @@ export type ToolMessageRenderer = (
const AssistantAudio = ({
content,
artifactId,
onRequestFileAccess,
}: {
content: SessionHistoryMessageContent;
artifactId?: string;
onRequestFileAccess?: (message: string) => void | Promise<void>;
}) => {
const resolvedUrl = useResolvedUrl({
src: content.url,
filePath: content.fileRef?.path,
environmentId: content.fileRef?.environmentId,
});
if (!resolvedUrl) return null;
if (!resolvedUrl) {
return shouldRenderFileReferenceFallback(content) ? (
<FileAttachmentCard
filename={content.fileName ?? 'Audio file'}
contentType={content.mimeType ?? 'audio/mpeg'}
path={content.fileRef?.path}
environmentId={content.fileRef?.environmentId ?? undefined}
size=""
data-artifact={artifactId}
onRequestFileAccess={onRequestFileAccess}
/>
) : null;
}
return (
<CueStreamdownAudio
src={resolvedUrl}
Expand All @@ -143,15 +160,31 @@ const AssistantAudio = ({

const AssistantVideo = ({
content,
artifactId,
onRequestFileAccess,
}: {
content: SessionHistoryMessageContent;
artifactId?: string;
onRequestFileAccess?: (message: string) => void | Promise<void>;
}) => {
const resolvedUrl = useResolvedUrl({
src: content.url,
filePath: content.fileRef?.path,
environmentId: content.fileRef?.environmentId,
});
if (!resolvedUrl) return null;
if (!resolvedUrl) {
return shouldRenderFileReferenceFallback(content) ? (
<FileAttachmentCard
filename={content.fileName ?? 'Video file'}
contentType={content.mimeType ?? 'video/mp4'}
path={content.fileRef?.path}
environmentId={content.fileRef?.environmentId ?? undefined}
size=""
data-artifact={artifactId}
onRequestFileAccess={onRequestFileAccess}
/>
) : null;
}
return (
<CueStreamdownVideo
src={resolvedUrl}
Expand Down Expand Up @@ -231,7 +264,8 @@ function renderContentBlock(
content: SessionHistoryMessageContent,
key: string,
isAnimating: boolean,
messageId: string
messageId: string,
onRequestFileAccess?: (message: string) => void | Promise<void>
) {
switch (content.type) {
case 'text':
Expand All @@ -247,6 +281,21 @@ function renderContentBlock(
</div>
) : null;
case 'image':
if (shouldRenderFileReferenceFallback(content)) {
return (
<FileAttachmentCard
key={key}
filename={content.fileName ?? 'Image file'}
contentType={content.mimeType ?? 'image/png'}
path={content.fileRef?.path}
environmentId={content.fileRef?.environmentId ?? undefined}
size=""
data-artifact={key}
onRequestFileAccess={onRequestFileAccess}
/>
);
}

return content.url || content.fileRef?.path ? (
<AttachmentImage
key={key}
Expand All @@ -261,11 +310,23 @@ function renderContentBlock(
) : null;
case 'audio':
return content.url || content.fileRef?.path ? (
<AssistantAudio key={key} content={content} artifactId={key} />
<AssistantAudio
key={key}
content={content}
artifactId={key}
onRequestFileAccess={onRequestFileAccess}
/>
) : null;
case 'video':
if (content.url || content.fileRef?.path) {
return <AssistantVideo key={key} content={content} />;
return (
<AssistantVideo
key={key}
content={content}
artifactId={key}
onRequestFileAccess={onRequestFileAccess}
/>
);
}
return null;
case 'file':
Expand All @@ -282,6 +343,7 @@ function renderContentBlock(
environmentId={content.fileRef?.environmentId ?? undefined}
size=""
data-artifact={key}
onRequestFileAccess={onRequestFileAccess}
/>
);
default:
Expand All @@ -299,6 +361,7 @@ export const AssistantMessage = ({
isAnimating = false,
hideOperations = false,
renderToolMessage,
onSendMessage,
}: {
items: AssistantGroupItem[];
allMessages: SessionHistoryMessage[];
Expand All @@ -309,6 +372,7 @@ export const AssistantMessage = ({
isAnimating?: boolean;
hideOperations?: boolean;
renderToolMessage?: ToolMessageRenderer;
onSendMessage?: (text: string) => void;
}) => {
const hasCurrentExecutionState = items.some(
item =>
Expand Down Expand Up @@ -633,7 +697,8 @@ export const AssistantMessage = ({
prepared,
`${msg.id || itemIndex}-${ci}`,
isAnimating,
msg.messageId ?? msg.id
msg.messageId ?? msg.id,
onSendMessage
);
})
.filter(Boolean);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ export const ConversationMessageGroupView = ({
activeTurnUserMessageId,
isStreaming,
renderToolMessage,
onSendMessage,
}: {
group: ConversationMessageGroup;
index: number;
Expand All @@ -277,6 +278,7 @@ export const ConversationMessageGroupView = ({
activeTurnUserMessageId?: string;
isStreaming: boolean;
renderToolMessage?: ToolMessageRenderer;
onSendMessage?: (text: string) => void;
}) => {
switch (group.type) {
case 'user':
Expand All @@ -286,6 +288,7 @@ export const ConversationMessageGroupView = ({
<UserMessage
message={group.message}
enterAnimation={isStreaming && index === totalGroups - 1}
onSendMessage={onSendMessage}
/>
</DebugMessage>
</ErrorBoundary>
Expand All @@ -311,6 +314,7 @@ export const ConversationMessageGroupView = ({
isAnimating={isActiveAssistantTurn}
hideOperations={hideOperations}
renderToolMessage={renderToolMessage}
onSendMessage={onSendMessage}
/>
</DebugMessage>
</ErrorBoundary>
Expand All @@ -327,12 +331,14 @@ export const ConversationThread = ({
isStreaming,
className,
renderToolMessage,
onSendMessage,
}: {
messages: SessionHistoryMessage[];
assistantStateSequence: AssistantState[];
isStreaming: boolean;
className?: string;
renderToolMessage?: ToolMessageRenderer;
onSendMessage?: (text: string) => void;
}) => {
const {
allMessages,
Expand Down Expand Up @@ -361,6 +367,7 @@ export const ConversationThread = ({
activeTurnUserMessageId={activeTurnUserMessageId}
isStreaming={isStreaming}
renderToolMessage={renderToolMessage}
onSendMessage={onSendMessage}
/>
))}
</div>
Expand Down
4 changes: 2 additions & 2 deletions web/src/embedded/chat/components/messages/copy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ export function collectUserMessageContent(
} else {
result.texts.push(c.text);
}
} else if (c.type === 'image' && c.url) {
} else if (c.type === 'image' && (c.url || c.fileRef?.path)) {
result.images.push(c);
} else if (c.type === 'audio') {
result.audios.push(c);
} else if (c.type === 'video') {
result.videos.push(c);
} else if (c.type === 'file' && c.url) {
} else if (c.type === 'file' && (c.url || c.fileRef?.path)) {
result.files.push({
filename: c.fileName ?? 'unknown',
contentType: c.mimeType ?? 'application/octet-stream',
Expand Down
Loading
Loading