summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamelmore <[email protected]>2026-01-26 16:46:01 -0600
committeradamelmore <[email protected]>2026-01-26 16:46:09 -0600
commit021d9d105e1dc8d096390b1b392de642c033901c (patch)
tree76754b375baf9327b6b03987e6a531103a3a2695
parentb07d7cdb71301b9b0381f1a94b5670f954a56d4c (diff)
downloadopencode-021d9d105e1dc8d096390b1b392de642c033901c.tar.gz
opencode-021d9d105e1dc8d096390b1b392de642c033901c.zip
fix(app): reactive file tree
-rw-r--r--packages/app/src/context/file.tsx12
-rw-r--r--packages/opencode/src/tool/apply_patch.ts15
-rw-r--r--packages/opencode/src/tool/edit.ts10
-rw-r--r--packages/opencode/src/tool/write.ts5
4 files changed, 35 insertions, 7 deletions
diff --git a/packages/app/src/context/file.tsx b/packages/app/src/context/file.tsx
index 306bce922..805936cd8 100644
--- a/packages/app/src/context/file.tsx
+++ b/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("/")
diff --git a/packages/opencode/src/tool/apply_patch.ts b/packages/opencode/src/tool/apply_patch.ts
index 8028ee8de..1344467c7 100644
--- a/packages/opencode/src/tool/apply_patch.ts
+++ b/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
diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts
index 26db5b228..0bf1d6792 100644
--- a/packages/opencode/src/tool/edit.ts
+++ b/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)),
diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts
index cfcf6a0da..eca64d303 100644
--- a/packages/opencode/src/tool/write.ts
+++ b/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."