@@ -24,7 +24,10 @@ import { CueStreamdownVideo } from '../markdown/overrides/video';
2424import { AttachmentImage } from './attachment-image' ;
2525import { AssistantMessageOperations } from './assistant-message-operations' ;
2626import { AssistantStateSection } from './assistant-state-section' ;
27- import { FileAttachmentCard } from './file-attachment' ;
27+ import {
28+ FileAttachmentCard ,
29+ shouldRenderFileReferenceFallback ,
30+ } from './file-attachment' ;
2831import { PermissionMessage } from './permission-message' ;
2932import { QuestionMessage } from './question-message' ;
3033import { SaveFileMessage } from './save-file-message' ;
@@ -119,16 +122,30 @@ export type ToolMessageRenderer = (
119122const AssistantAudio = ( {
120123 content,
121124 artifactId,
125+ onRequestFileAccess,
122126} : {
123127 content : SessionHistoryMessageContent ;
124128 artifactId ?: string ;
129+ onRequestFileAccess ?: ( message : string ) => void | Promise < void > ;
125130} ) => {
126131 const resolvedUrl = useResolvedUrl ( {
127132 src : content . url ,
128133 filePath : content . fileRef ?. path ,
129134 environmentId : content . fileRef ?. environmentId ,
130135 } ) ;
131- if ( ! resolvedUrl ) return null ;
136+ if ( ! resolvedUrl ) {
137+ return shouldRenderFileReferenceFallback ( content ) ? (
138+ < FileAttachmentCard
139+ filename = { content . fileName ?? 'Audio file' }
140+ contentType = { content . mimeType ?? 'audio/mpeg' }
141+ path = { content . fileRef ?. path }
142+ environmentId = { content . fileRef ?. environmentId ?? undefined }
143+ size = ""
144+ data-artifact = { artifactId }
145+ onRequestFileAccess = { onRequestFileAccess }
146+ />
147+ ) : null ;
148+ }
132149 return (
133150 < CueStreamdownAudio
134151 src = { resolvedUrl }
@@ -143,15 +160,31 @@ const AssistantAudio = ({
143160
144161const AssistantVideo = ( {
145162 content,
163+ artifactId,
164+ onRequestFileAccess,
146165} : {
147166 content : SessionHistoryMessageContent ;
167+ artifactId ?: string ;
168+ onRequestFileAccess ?: ( message : string ) => void | Promise < void > ;
148169} ) => {
149170 const resolvedUrl = useResolvedUrl ( {
150171 src : content . url ,
151172 filePath : content . fileRef ?. path ,
152173 environmentId : content . fileRef ?. environmentId ,
153174 } ) ;
154- if ( ! resolvedUrl ) return null ;
175+ if ( ! resolvedUrl ) {
176+ return shouldRenderFileReferenceFallback ( content ) ? (
177+ < FileAttachmentCard
178+ filename = { content . fileName ?? 'Video file' }
179+ contentType = { content . mimeType ?? 'video/mp4' }
180+ path = { content . fileRef ?. path }
181+ environmentId = { content . fileRef ?. environmentId ?? undefined }
182+ size = ""
183+ data-artifact = { artifactId }
184+ onRequestFileAccess = { onRequestFileAccess }
185+ />
186+ ) : null ;
187+ }
155188 return (
156189 < CueStreamdownVideo
157190 src = { resolvedUrl }
@@ -231,7 +264,8 @@ function renderContentBlock(
231264 content : SessionHistoryMessageContent ,
232265 key : string ,
233266 isAnimating : boolean ,
234- messageId : string
267+ messageId : string ,
268+ onRequestFileAccess ?: ( message : string ) => void | Promise < void >
235269) {
236270 switch ( content . type ) {
237271 case 'text' :
@@ -247,6 +281,21 @@ function renderContentBlock(
247281 </ div >
248282 ) : null ;
249283 case 'image' :
284+ if ( shouldRenderFileReferenceFallback ( content ) ) {
285+ return (
286+ < FileAttachmentCard
287+ key = { key }
288+ filename = { content . fileName ?? 'Image file' }
289+ contentType = { content . mimeType ?? 'image/png' }
290+ path = { content . fileRef ?. path }
291+ environmentId = { content . fileRef ?. environmentId ?? undefined }
292+ size = ""
293+ data-artifact = { key }
294+ onRequestFileAccess = { onRequestFileAccess }
295+ />
296+ ) ;
297+ }
298+
250299 return content . url || content . fileRef ?. path ? (
251300 < AttachmentImage
252301 key = { key }
@@ -261,11 +310,23 @@ function renderContentBlock(
261310 ) : null ;
262311 case 'audio' :
263312 return content . url || content . fileRef ?. path ? (
264- < AssistantAudio key = { key } content = { content } artifactId = { key } />
313+ < AssistantAudio
314+ key = { key }
315+ content = { content }
316+ artifactId = { key }
317+ onRequestFileAccess = { onRequestFileAccess }
318+ />
265319 ) : null ;
266320 case 'video' :
267321 if ( content . url || content . fileRef ?. path ) {
268- return < AssistantVideo key = { key } content = { content } /> ;
322+ return (
323+ < AssistantVideo
324+ key = { key }
325+ content = { content }
326+ artifactId = { key }
327+ onRequestFileAccess = { onRequestFileAccess }
328+ />
329+ ) ;
269330 }
270331 return null ;
271332 case 'file' :
@@ -282,6 +343,7 @@ function renderContentBlock(
282343 environmentId = { content . fileRef ?. environmentId ?? undefined }
283344 size = ""
284345 data-artifact = { key }
346+ onRequestFileAccess = { onRequestFileAccess }
285347 />
286348 ) ;
287349 default :
@@ -299,6 +361,7 @@ export const AssistantMessage = ({
299361 isAnimating = false ,
300362 hideOperations = false ,
301363 renderToolMessage,
364+ onSendMessage,
302365} : {
303366 items : AssistantGroupItem [ ] ;
304367 allMessages : SessionHistoryMessage [ ] ;
@@ -309,6 +372,7 @@ export const AssistantMessage = ({
309372 isAnimating ?: boolean ;
310373 hideOperations ?: boolean ;
311374 renderToolMessage ?: ToolMessageRenderer ;
375+ onSendMessage ?: ( text : string ) => void ;
312376} ) => {
313377 const hasCurrentExecutionState = items . some (
314378 item =>
@@ -633,7 +697,8 @@ export const AssistantMessage = ({
633697 prepared ,
634698 `${ msg . id || itemIndex } -${ ci } ` ,
635699 isAnimating ,
636- msg . messageId ?? msg . id
700+ msg . messageId ?? msg . id ,
701+ onSendMessage
637702 ) ;
638703 } )
639704 . filter ( Boolean ) ;
0 commit comments