src / fsTools.ts
import { tool, text } from "@lmstudio/sdk";
import { z } from "zod";
import {
readFile,
writeFile,
readdir,
unlink,
rename,
} from "fs/promises";
import { stat } from "fs/promises";
import DiffMatchPatch from "diff-match-patch";
const dmp = new DiffMatchPatch();
/* ---------------------------
READ FILE
--------------------------- */
export function createReadFileTool() {
return tool({
name: "read_file",
description: text`Read a file`,
parameters: {
path: z.string(),
},
implementation: async ({ path }) => {
const content = await readFile(path, "utf-8");
return { path, content };
},
});
}
/* ---------------------------
WRITE FILE (FULL)
--------------------------- */
export function createWriteFileTool() {
return tool({
name: "write_file",
description: text`Overwrite a file completely`,
parameters: {
path: z.string(),
content: z.string(),
},
implementation: async ({ path, content }) => {
await writeFile(path, content, "utf-8");
return { path, status: "written" };
},
});
}
/* ---------------------------
WRITE FILE (DIFF PATCH)
--------------------------- */
export function createWriteFileDiffTool() {
return tool({
name: "write_file_diff",
description: text`
Apply a unified diff patch to a file.
Safer than full overwrite. Only modifies changed sections.
`,
parameters: {
path: z.string(),
diff: z.string(),
},
implementation: async ({ path, diff }) => {
const original = await readFile(path, "utf-8");
const patches = dmp.patch_fromText(diff);
const [result, applied] = dmp.patch_apply(patches, original);
const success = applied.every(Boolean);
if (!success) {
return {
ok: false,
error: "patch failed to apply",
};
}
await writeFile(path, result, "utf-8");
return {
ok: true,
path,
changed: true,
};
},
});
}
/* ---------------------------
LIST DIR
--------------------------- */
export function createListDirTool() {
return tool({
name: "list_dir",
description: text`List directory`,
parameters: {
path: z.string(),
},
implementation: async ({ path }) => {
const files = await readdir(path, { withFileTypes: true });
return files.map(f => ({
name: f.name,
is_dir: f.isDirectory(),
}));
},
});
}
/* ---------------------------
DELETE FILE
--------------------------- */
export function createDeleteFileTool() {
return tool({
name: "delete_file",
description: text`Delete file`,
parameters: {
path: z.string(),
},
implementation: async ({ path }) => {
await unlink(path);
return { path, deleted: true };
},
});
}
/* ---------------------------
MOVE FILE
--------------------------- */
export function createMoveFileTool() {
return tool({
name: "move_file",
description: text`Move/rename file`,
parameters: {
from: z.string(),
to: z.string(),
},
implementation: async ({ from, to }) => {
await rename(from, to);
return { from, to, moved: true };
},
});
}
export function createFileInfoTool(cwd: string) {
return tool({
name: "file_info",
description: text`Get file metadata`,
parameters: {
path: z.string(),
},
implementation: async ({ path }) => {
const full = `${cwd}/${path}`;
const s = await stat(full);
return {
path,
size: s.size,
is_file: s.isFile(),
is_dir: s.isDirectory(),
modified: s.mtime,
};
},
});
}