@@ -200,21 +200,12 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
200200 }
201201 }
202202
203- // Track the last seen path during streaming to detect when the path has stabilized
204- private lastSeenPartialPath : string | undefined = undefined
205-
206203 override async handlePartial ( task : Task , block : ToolUse < "write_to_file" > ) : Promise < void > {
207204 const relPath : string | undefined = block . params . path
208205 let newContent : string | undefined = block . params . content
209206
210- // During streaming, the partial-json library may return truncated string values
211- // when chunk boundaries fall mid-value. To avoid creating files at incorrect paths,
212- // we wait until the path stops changing between consecutive partial blocks before
213- // creating the file. This ensures we have the complete, final path value.
214- const pathHasStabilized = this . lastSeenPartialPath !== undefined && this . lastSeenPartialPath === relPath
215- this . lastSeenPartialPath = relPath
216-
217- if ( ! pathHasStabilized || ! relPath || newContent === undefined ) {
207+ // Wait for path to stabilize before showing UI (prevents truncated paths)
208+ if ( ! this . hasPathStabilized ( relPath ) || newContent === undefined ) {
218209 return
219210 }
220211
@@ -229,8 +220,9 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
229220 return
230221 }
231222
223+ // relPath is guaranteed non-null after hasPathStabilized
232224 let fileExists : boolean
233- const absolutePath = path . resolve ( task . cwd , relPath )
225+ const absolutePath = path . resolve ( task . cwd , relPath ! )
234226
235227 if ( task . diffViewProvider . editType !== undefined ) {
236228 fileExists = task . diffViewProvider . editType === "modify"
@@ -245,13 +237,12 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
245237 await createDirectoriesForFile ( absolutePath )
246238 }
247239
248- const isWriteProtected = task . rooProtectedController ?. isWriteProtected ( relPath ) || false
249- const fullPath = absolutePath
250- const isOutsideWorkspace = isPathOutsideWorkspace ( fullPath )
240+ const isWriteProtected = task . rooProtectedController ?. isWriteProtected ( relPath ! ) || false
241+ const isOutsideWorkspace = isPathOutsideWorkspace ( absolutePath )
251242
252243 const sharedMessageProps : ClineSayTool = {
253244 tool : fileExists ? "editedExistingFile" : "newFileCreated" ,
254- path : getReadablePath ( task . cwd , relPath ) ,
245+ path : getReadablePath ( task . cwd , relPath ! ) ,
255246 content : newContent || "" ,
256247 isOutsideWorkspace,
257248 isProtected : isWriteProtected ,
@@ -262,7 +253,7 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
262253
263254 if ( newContent ) {
264255 if ( ! task . diffViewProvider . isEditing ) {
265- await task . diffViewProvider . open ( relPath )
256+ await task . diffViewProvider . open ( relPath ! )
266257 }
267258
268259 await task . diffViewProvider . update (
@@ -271,13 +262,6 @@ export class WriteToFileTool extends BaseTool<"write_to_file"> {
271262 )
272263 }
273264 }
274-
275- /**
276- * Reset state when the tool finishes (called from execute or on error)
277- */
278- resetPartialState ( ) : void {
279- this . lastSeenPartialPath = undefined
280- }
281265}
282266
283267export const writeToFileTool = new WriteToFileTool ( )
0 commit comments