Browse Source

fix(app): reactive file tree

adamelmore 3 weeks ago
parent
commit
021d9d105e

+ 12 - 0
packages/app/src/context/file.tsx

@@ -571,6 +571,18 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({
       }
 
       const kind = event.properties.event
+      if (kind === "change") {
+        const dir = (() => {
+          if (path === "") return ""
+          const node = tree.node[path]
+          if (node?.type !== "directory") return
+          return path
+        })()
+        if (dir === undefined) return
+        if (!tree.dir[dir]?.loaded) return
+        listDir(dir, { force: true })
+        return
+      }
       if (kind !== "add" && kind !== "unlink") return
 
       const parent = path.split("/").slice(0, -1).join("/")

+ 8 - 7
packages/opencode/src/tool/apply_patch.ts

@@ -185,7 +185,7 @@ export const ApplyPatchTool = Tool.define("apply_patch", {
     })
 
     // Apply the changes
-    const changedFiles: string[] = []
+    const updates: Array<{ file: string; event: "add" | "change" | "unlink" }> = []
 
     for (const change of fileChanges) {
       const edited = change.type === "delete" ? undefined : (change.movePath ?? change.filePath)
@@ -194,12 +194,12 @@ export const ApplyPatchTool = Tool.define("apply_patch", {
           // Create parent directories (recursive: true is safe on existing/root dirs)
           await fs.mkdir(path.dirname(change.filePath), { recursive: true })
           await fs.writeFile(change.filePath, change.newContent, "utf-8")
-          changedFiles.push(change.filePath)
+          updates.push({ file: change.filePath, event: "add" })
           break
 
         case "update":
           await fs.writeFile(change.filePath, change.newContent, "utf-8")
-          changedFiles.push(change.filePath)
+          updates.push({ file: change.filePath, event: "change" })
           break
 
         case "move":
@@ -208,13 +208,14 @@ export const ApplyPatchTool = Tool.define("apply_patch", {
             await fs.mkdir(path.dirname(change.movePath), { recursive: true })
             await fs.writeFile(change.movePath, change.newContent, "utf-8")
             await fs.unlink(change.filePath)
-            changedFiles.push(change.movePath)
+            updates.push({ file: change.filePath, event: "unlink" })
+            updates.push({ file: change.movePath, event: "add" })
           }
           break
 
         case "delete":
           await fs.unlink(change.filePath)
-          changedFiles.push(change.filePath)
+          updates.push({ file: change.filePath, event: "unlink" })
           break
       }
 
@@ -226,8 +227,8 @@ export const ApplyPatchTool = Tool.define("apply_patch", {
     }
 
     // Publish file change events
-    for (const filePath of changedFiles) {
-      await Bus.publish(FileWatcher.Event.Updated, { file: filePath, event: "change" })
+    for (const update of updates) {
+      await Bus.publish(FileWatcher.Event.Updated, update)
     }
 
     // Notify LSP of file changes and collect diagnostics

+ 10 - 0
packages/opencode/src/tool/edit.ts

@@ -10,6 +10,7 @@ import { LSP } from "../lsp"
 import { createTwoFilesPatch, diffLines } from "diff"
 import DESCRIPTION from "./edit.txt"
 import { File } from "../file"
+import { FileWatcher } from "../file/watcher"
 import { Bus } from "../bus"
 import { FileTime } from "../file/time"
 import { Filesystem } from "../util/filesystem"
@@ -48,6 +49,7 @@ export const EditTool = Tool.define("edit", {
     let contentNew = ""
     await FileTime.withLock(filePath, async () => {
       if (params.oldString === "") {
+        const existed = await Bun.file(filePath).exists()
         contentNew = params.newString
         diff = trimDiff(createTwoFilesPatch(filePath, filePath, contentOld, contentNew))
         await ctx.ask({
@@ -63,6 +65,10 @@ export const EditTool = Tool.define("edit", {
         await Bus.publish(File.Event.Edited, {
           file: filePath,
         })
+        await Bus.publish(FileWatcher.Event.Updated, {
+          file: filePath,
+          event: existed ? "change" : "add",
+        })
         FileTime.read(ctx.sessionID, filePath)
         return
       }
@@ -92,6 +98,10 @@ export const EditTool = Tool.define("edit", {
       await Bus.publish(File.Event.Edited, {
         file: filePath,
       })
+      await Bus.publish(FileWatcher.Event.Updated, {
+        file: filePath,
+        event: "change",
+      })
       contentNew = await file.text()
       diff = trimDiff(
         createTwoFilesPatch(filePath, filePath, normalizeLineEndings(contentOld), normalizeLineEndings(contentNew)),

+ 5 - 0
packages/opencode/src/tool/write.ts

@@ -6,6 +6,7 @@ import { createTwoFilesPatch } from "diff"
 import DESCRIPTION from "./write.txt"
 import { Bus } from "../bus"
 import { File } from "../file"
+import { FileWatcher } from "../file/watcher"
 import { FileTime } from "../file/time"
 import { Filesystem } from "../util/filesystem"
 import { Instance } from "../project/instance"
@@ -45,6 +46,10 @@ export const WriteTool = Tool.define("write", {
     await Bus.publish(File.Event.Edited, {
       file: filepath,
     })
+    await Bus.publish(FileWatcher.Event.Updated, {
+      file: filepath,
+      event: exists ? "change" : "add",
+    })
     FileTime.read(ctx.sessionID, filepath)
 
     let output = "Wrote file successfully."