@@ -15,6 +15,7 @@ import {
1515 deleteWorkspaceFile ,
1616 downloadWorkspaceFile as downloadWsFile ,
1717 getWorkspaceFile ,
18+ getWorkspaceFileByName ,
1819 renameWorkspaceFile ,
1920 updateWorkspaceFileContent ,
2021 uploadWorkspaceFile ,
@@ -99,20 +100,76 @@ export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, Workspac
99100 const isPptx = lowerName . endsWith ( '.pptx' )
100101 const isDocx = lowerName . endsWith ( '.docx' )
101102 const isPdf = lowerName . endsWith ( '.pdf' )
102- let contentType : string
103+ const isDoc = isPptx || isDocx || isPdf
104+ const sourceMime = isPptx
105+ ? PPTX_SOURCE_MIME
106+ : isDocx
107+ ? DOCX_SOURCE_MIME
108+ : isPdf
109+ ? PDF_SOURCE_MIME
110+ : undefined
103111
104- if ( isPptx || isDocx || isPdf ) {
112+ const existingFile = await getWorkspaceFileByName ( workspaceId , fileName )
113+
114+ if ( existingFile ) {
115+ const currentBuffer = await downloadWsFile ( existingFile )
116+ const combined = `${ currentBuffer . toString ( 'utf-8' ) } \n${ content } `
117+
118+ if ( isDoc ) {
119+ const formatName = isPptx ? 'PPTX' : isDocx ? 'DOCX' : 'PDF'
120+ const generator = isPptx
121+ ? generatePptxFromCode
122+ : isDocx
123+ ? generateDocxFromCode
124+ : generatePdfFromCode
125+ try {
126+ await generator ( combined , workspaceId )
127+ } catch ( err ) {
128+ const msg = err instanceof Error ? err . message : String ( err )
129+ return {
130+ success : false ,
131+ message : `${ formatName } generation failed after append: ${ msg } . Fix the content and retry.` ,
132+ }
133+ }
134+ }
135+
136+ const combinedBuffer = Buffer . from ( combined , 'utf-8' )
137+ assertServerToolNotAborted ( context )
138+ await updateWorkspaceFileContent (
139+ workspaceId ,
140+ existingFile . id ,
141+ context . userId ,
142+ combinedBuffer ,
143+ sourceMime
144+ )
145+
146+ logger . info ( 'Workspace file appended via write' , {
147+ fileId : existingFile . id ,
148+ name : fileName ,
149+ appendedSize : content . length ,
150+ totalSize : combinedBuffer . length ,
151+ userId : context . userId ,
152+ } )
153+
154+ return {
155+ success : true ,
156+ message : `Content appended to "${ fileName } " (${ content . length } bytes added, ${ combinedBuffer . length } bytes total)` ,
157+ data : {
158+ id : existingFile . id ,
159+ name : fileName ,
160+ size : combinedBuffer . length ,
161+ } ,
162+ }
163+ }
164+
165+ let contentType : string
166+ if ( isDoc ) {
105167 const formatName = isPptx ? 'PPTX' : isDocx ? 'DOCX' : 'PDF'
106168 const generator = isPptx
107169 ? generatePptxFromCode
108170 : isDocx
109171 ? generateDocxFromCode
110172 : generatePdfFromCode
111- const sourceMime = isPptx
112- ? PPTX_SOURCE_MIME
113- : isDocx
114- ? DOCX_SOURCE_MIME
115- : PDF_SOURCE_MIME
116173 try {
117174 await generator ( content , workspaceId )
118175 } catch ( err ) {
@@ -123,7 +180,7 @@ export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, Workspac
123180 message : `${ formatName } generation failed: ${ msg } . Fix the code and retry.` ,
124181 }
125182 }
126- contentType = sourceMime
183+ contentType = sourceMime !
127184 } else {
128185 contentType = inferContentType ( fileName , explicitType )
129186 }
@@ -301,85 +358,6 @@ export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, Workspac
301358 }
302359 }
303360
304- case 'append' : {
305- const fileId = ( args as Record < string , unknown > ) . fileId as string | undefined
306- const content = ( args as Record < string , unknown > ) . content as string | undefined
307-
308- if ( ! fileId ) {
309- return { success : false , message : 'fileId is required for append operation' }
310- }
311- if ( ! content ) {
312- return { success : false , message : 'content is required for append operation' }
313- }
314-
315- const fileRecord = await getWorkspaceFile ( workspaceId , fileId )
316- if ( ! fileRecord ) {
317- return { success : false , message : `File with ID "${ fileId } " not found` }
318- }
319-
320- const currentBuffer = await downloadWsFile ( fileRecord )
321- const combined = `${ currentBuffer . toString ( 'utf-8' ) } \n${ content } `
322-
323- const appendLowerName = fileRecord . name ?. toLowerCase ( ) ?? ''
324- const isPptxAppend = appendLowerName . endsWith ( '.pptx' )
325- const isDocxAppend = appendLowerName . endsWith ( '.docx' )
326- const isPdfAppend = appendLowerName . endsWith ( '.pdf' )
327- const isDocAppend = isPptxAppend || isDocxAppend || isPdfAppend
328-
329- if ( isDocAppend ) {
330- const formatName = isPptxAppend ? 'PPTX' : isDocxAppend ? 'DOCX' : 'PDF'
331- const generator = isPptxAppend
332- ? generatePptxFromCode
333- : isDocxAppend
334- ? generateDocxFromCode
335- : generatePdfFromCode
336- try {
337- await generator ( combined , workspaceId )
338- } catch ( err ) {
339- const msg = err instanceof Error ? err . message : String ( err )
340- return {
341- success : false ,
342- message : `Appended ${ formatName } code failed to compile: ${ msg } . Fix the content and retry.` ,
343- }
344- }
345- }
346-
347- const appendSourceMime = isPptxAppend
348- ? PPTX_SOURCE_MIME
349- : isDocxAppend
350- ? DOCX_SOURCE_MIME
351- : isPdfAppend
352- ? PDF_SOURCE_MIME
353- : undefined
354- const appendBuffer = Buffer . from ( combined , 'utf-8' )
355- assertServerToolNotAborted ( context )
356- await updateWorkspaceFileContent (
357- workspaceId ,
358- fileId ,
359- context . userId ,
360- appendBuffer ,
361- appendSourceMime
362- )
363-
364- logger . info ( 'Workspace file appended via copilot' , {
365- fileId,
366- name : fileRecord . name ,
367- appendedSize : content . length ,
368- totalSize : appendBuffer . length ,
369- userId : context . userId ,
370- } )
371-
372- return {
373- success : true ,
374- message : `Content appended to "${ fileRecord . name } " (${ content . length } bytes added, ${ appendBuffer . length } bytes total)` ,
375- data : {
376- id : fileId ,
377- name : fileRecord . name ,
378- size : appendBuffer . length ,
379- } ,
380- }
381- }
382-
383361 case 'patch' : {
384362 const fileId = ( args as Record < string , unknown > ) . fileId as string | undefined
385363 const edits = ( args as Record < string , unknown > ) . edits as
0 commit comments