write.ts 2.1 KB

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