write.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { z } from "zod"
  2. import * as path from "path"
  3. import { Tool } from "./tool"
  4. import { LSP } from "../lsp"
  5. import { Permission } from "../permission"
  6. import DESCRIPTION from "./write.txt"
  7. import { App } from "../app/app"
  8. import { Bus } from "../bus"
  9. import { File } from "../file"
  10. import { FileTime } from "../file/time"
  11. export const WriteTool = Tool.define({
  12. id: "write",
  13. description: DESCRIPTION,
  14. parameters: z.object({
  15. filePath: z.string().describe("The absolute path to the file to write (must be absolute, not relative)"),
  16. content: z.string().describe("The content to write to the file"),
  17. }),
  18. async execute(params, ctx) {
  19. const app = App.info()
  20. const filepath = path.isAbsolute(params.filePath) ? params.filePath : path.join(app.path.cwd, params.filePath)
  21. const file = Bun.file(filepath)
  22. const exists = await file.exists()
  23. if (exists) await FileTime.assert(ctx.sessionID, filepath)
  24. await Permission.ask({
  25. id: "write",
  26. sessionID: ctx.sessionID,
  27. title: exists ? "Overwrite this file: " + filepath : "Create new file: " + filepath,
  28. metadata: {
  29. filePath: filepath,
  30. content: params.content,
  31. exists,
  32. },
  33. })
  34. await Bun.write(filepath, params.content)
  35. await Bus.publish(File.Event.Edited, {
  36. file: filepath,
  37. })
  38. FileTime.read(ctx.sessionID, filepath)
  39. let output = ""
  40. await LSP.touchFile(filepath, true)
  41. const diagnostics = await LSP.diagnostics()
  42. for (const [file, issues] of Object.entries(diagnostics)) {
  43. if (issues.length === 0) continue
  44. if (file === filepath) {
  45. output += `\nThis file has errors, please fix\n<file_diagnostics>\n${issues.map(LSP.Diagnostic.pretty).join("\n")}\n</file_diagnostics>\n`
  46. continue
  47. }
  48. output += `\n<project_diagnostics>\n${file}\n${issues.map(LSP.Diagnostic.pretty).join("\n")}\n</project_diagnostics>\n`
  49. }
  50. return {
  51. title: path.relative(app.path.root, filepath),
  52. metadata: {
  53. diagnostics,
  54. filepath,
  55. exists: exists,
  56. },
  57. output,
  58. }
  59. },
  60. })