@@ -85,11 +85,16 @@ export const ResourceContent = memo(function ResourceContent({
8585} : ResourceContentProps ) {
8686 const streamFileName = streamingFile ?. fileName || 'file.md'
8787
88- const isPatchStream = useMemo ( ( ) => {
89- if ( ! streamingFile ) return false
90- return / " o p e r a t i o n " \s * : \s * " p a t c h " / . test ( streamingFile . content )
88+ const streamOperation = useMemo ( ( ) => {
89+ if ( ! streamingFile ) return undefined
90+ const m = streamingFile . content . match ( / " o p e r a t i o n " \s * : \s * " ( \w + ) " / )
91+ return m ?. [ 1 ]
9192 } , [ streamingFile ] )
9293
94+ const isWriteStream = streamOperation === 'write'
95+ const isPatchStream = streamOperation === 'patch'
96+ const isUpdateStream = streamOperation === 'update'
97+
9398 const { data : allFiles = [ ] } = useWorkspaceFiles ( workspaceId )
9499 const activeFileRecord = useMemo ( ( ) => {
95100 if ( ! isPatchStream || resource . type !== 'file' ) return undefined
@@ -112,13 +117,25 @@ export const ResourceContent = memo(function ResourceContent({
112117 if ( ! streamingFile ) return undefined
113118 const raw = streamingFile . content
114119
115- if ( isPatchStream && fetchedFileContent ) {
120+ // Do not guess. Until the operation key has streamed in, we don't know
121+ // whether the payload should append, replace, or splice into the file.
122+ // Rendering early here can show content at the end of the file and then
123+ // "snap" to the right place once the operation/mode becomes known.
124+ if ( ! streamOperation ) return undefined
125+
126+ if ( isPatchStream ) {
127+ if ( ! fetchedFileContent ) return undefined
116128 return extractPatchPreview ( raw , fetchedFileContent )
117129 }
118130
119131 const extracted = extractFileContent ( raw )
120- return extracted . length > 0 ? extracted : undefined
121- } , [ streamingFile , isPatchStream , fetchedFileContent ] )
132+ if ( extracted . length === 0 ) return undefined
133+
134+ if ( isUpdateStream ) return extracted
135+ if ( isWriteStream ) return extracted
136+
137+ return undefined
138+ } , [ streamingFile , streamOperation , isWriteStream , isPatchStream , isUpdateStream , fetchedFileContent ] )
122139 const syntheticFile = useMemo ( ( ) => {
123140 const ext = getFileExtension ( streamFileName )
124141 const SOURCE_MIME_MAP : Record < string , string > = {
@@ -140,6 +157,9 @@ export const ResourceContent = memo(function ResourceContent({
140157 }
141158 } , [ workspaceId , streamFileName ] )
142159
160+ const streamingFileMode : 'append' | 'replace' =
161+ isWriteStream ? 'append' : 'replace'
162+
143163 if ( streamingFile && resource . id === 'streaming-file' ) {
144164 return (
145165 < div className = 'flex h-full flex-col overflow-hidden' >
@@ -150,6 +170,7 @@ export const ResourceContent = memo(function ResourceContent({
150170 canEdit = { false }
151171 previewMode = { previewMode ?? 'preview' }
152172 streamingContent = { streamingExtractedContent }
173+ streamingMode = { streamingFileMode }
153174 />
154175 ) : (
155176 < div className = 'flex h-full items-center justify-center' >
@@ -172,6 +193,7 @@ export const ResourceContent = memo(function ResourceContent({
172193 fileId = { resource . id }
173194 previewMode = { previewMode }
174195 streamingContent = { streamingExtractedContent }
196+ streamingMode = { streamingFileMode }
175197 />
176198 )
177199
@@ -460,9 +482,10 @@ interface EmbeddedFileProps {
460482 fileId : string
461483 previewMode ?: PreviewMode
462484 streamingContent ?: string
485+ streamingMode ?: 'append' | 'replace'
463486}
464487
465- function EmbeddedFile ( { workspaceId, fileId, previewMode, streamingContent } : EmbeddedFileProps ) {
488+ function EmbeddedFile ( { workspaceId, fileId, previewMode, streamingContent, streamingMode } : EmbeddedFileProps ) {
466489 const { canEdit } = useUserPermissionsContext ( )
467490 const { data : files = [ ] , isLoading, isFetching } = useWorkspaceFiles ( workspaceId )
468491 const file = useMemo ( ( ) => files . find ( ( f ) => f . id === fileId ) , [ files , fileId ] )
@@ -490,6 +513,7 @@ function EmbeddedFile({ workspaceId, fileId, previewMode, streamingContent }: Em
490513 file = { file }
491514 workspaceId = { workspaceId }
492515 canEdit = { canEdit }
516+ streamingMode = { streamingMode }
493517 previewMode = { previewMode }
494518 streamingContent = { streamingContent }
495519 />
0 commit comments