lazy load formatters

This commit is contained in:
Dax Raad
2025-06-27 11:29:20 -04:00
parent 334161a30e
commit 2ec0611f42
19 changed files with 408 additions and 435 deletions

View File

@@ -5,13 +5,14 @@
import { z } from "zod"
import * as path from "path"
import { Tool } from "./tool"
import { FileTimes } from "./util/file-times"
import { LSP } from "../lsp"
import { createTwoFilesPatch } from "diff"
import { Permission } from "../permission"
import DESCRIPTION from "./edit.txt"
import { App } from "../app/app"
import { Format } from "../format"
import { File } from "../file"
import { Bus } from "../bus"
import { FileTime } from "../file/time"
export const EditTool = Tool.define({
id: "edit",
@@ -60,7 +61,9 @@ export const EditTool = Tool.define({
if (params.oldString === "") {
contentNew = params.newString
await Bun.write(filepath, params.newString)
await Format.run(filepath)
await Bus.publish(File.Event.Edited, {
file: filepath,
})
return
}
@@ -69,7 +72,7 @@ export const EditTool = Tool.define({
if (!stats) throw new Error(`File ${filepath} not found`)
if (stats.isDirectory())
throw new Error(`Path is a directory, not a file: ${filepath}`)
await FileTimes.assert(ctx.sessionID, filepath)
await FileTime.assert(ctx.sessionID, filepath)
contentOld = await file.text()
contentNew = replace(
@@ -79,7 +82,9 @@ export const EditTool = Tool.define({
params.replaceAll,
)
await file.write(contentNew)
await Format.run(filepath)
await Bus.publish(File.Event.Edited, {
file: filepath,
})
contentNew = await file.text()
})()
@@ -87,7 +92,7 @@ export const EditTool = Tool.define({
createTwoFilesPatch(filepath, filepath, contentOld, contentNew),
)
FileTimes.read(ctx.sessionID, filepath)
FileTime.read(ctx.sessionID, filepath)
let output = ""
await LSP.touchFile(filepath, true)

View File

@@ -2,7 +2,7 @@ import { z } from "zod"
import * as path from "path"
import * as fs from "fs/promises"
import { Tool } from "./tool"
import { FileTimes } from "./util/file-times"
import { FileTime } from "../file/time"
import DESCRIPTION from "./patch.txt"
const PatchParams = z.object({
@@ -244,7 +244,7 @@ export const PatchTool = Tool.define({
absPath = path.resolve(process.cwd(), absPath)
}
await FileTimes.assert(ctx.sessionID, absPath)
await FileTime.assert(ctx.sessionID, absPath)
try {
const stats = await fs.stat(absPath)
@@ -351,7 +351,7 @@ export const PatchTool = Tool.define({
totalAdditions += additions
totalRemovals += removals
FileTimes.read(ctx.sessionID, absPath)
FileTime.read(ctx.sessionID, absPath)
}
const result = `Patch applied successfully. ${changedFiles.length} files changed, ${totalAdditions} additions, ${totalRemovals} removals`

View File

@@ -3,7 +3,7 @@ import * as fs from "fs"
import * as path from "path"
import { Tool } from "./tool"
import { LSP } from "../lsp"
import { FileTimes } from "./util/file-times"
import { FileTime } from "../file/time"
import DESCRIPTION from "./read.txt"
import { App } from "../app/app"
@@ -90,7 +90,7 @@ export const ReadTool = Tool.define({
// just warms the lsp client
await LSP.touchFile(filePath, true)
FileTimes.read(ctx.sessionID, filePath)
FileTime.read(ctx.sessionID, filePath)
return {
output,

View File

@@ -1,38 +0,0 @@
import { App } from "../../app/app"
export namespace FileTimes {
export const state = App.state("tool.filetimes", () => {
const read: {
[sessionID: string]: {
[path: string]: Date | undefined
}
} = {}
return {
read,
}
})
export function read(sessionID: string, file: string) {
const { read } = state()
read[sessionID] = read[sessionID] || {}
read[sessionID][file] = new Date()
}
export function get(sessionID: string, file: string) {
return state().read[sessionID]?.[file]
}
export async function assert(sessionID: string, filepath: string) {
const time = get(sessionID, filepath)
if (!time)
throw new Error(
`You must read the file ${filepath} before overwriting it. Use the Read tool first`,
)
const stats = await Bun.file(filepath).stat()
if (stats.mtime.getTime() > time.getTime()) {
throw new Error(
`File ${filepath} has been modified since it was last read.\nLast modification: ${stats.mtime.toISOString()}\nLast read: ${time.toISOString()}\n\nPlease read the file again before modifying it.`,
)
}
}
}

View File

@@ -1,12 +1,13 @@
import { z } from "zod"
import * as path from "path"
import { Tool } from "./tool"
import { FileTimes } from "./util/file-times"
import { LSP } from "../lsp"
import { Permission } from "../permission"
import DESCRIPTION from "./write.txt"
import { App } from "../app/app"
import { Format } from "../format"
import { Bus } from "../bus"
import { File } from "../file"
import { FileTime } from "../file/time"
export const WriteTool = Tool.define({
id: "write",
@@ -27,7 +28,7 @@ export const WriteTool = Tool.define({
const file = Bun.file(filepath)
const exists = await file.exists()
if (exists) await FileTimes.assert(ctx.sessionID, filepath)
if (exists) await FileTime.assert(ctx.sessionID, filepath)
await Permission.ask({
id: "write",
@@ -43,8 +44,10 @@ export const WriteTool = Tool.define({
})
await Bun.write(filepath, params.content)
await Format.run(filepath)
FileTimes.read(ctx.sessionID, filepath)
await Bus.publish(File.Event.Edited, {
file: filepath,
})
FileTime.read(ctx.sessionID, filepath)
let output = ""
await LSP.touchFile(filepath, true)