blob: e003099f5f085e6705f61cf5a2b05918707ab191 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
import { readdir } from "node:fs/promises";
import { z } from "zod";
import type { ToolDefinition } from "../types/index.js";
import { canonicalize } from "./path-utils.js";
export function createListFilesTool(workingDirectory: string): ToolDefinition {
return {
name: "list_files",
description: "List files and directories at a path relative to the working directory.",
parameters: z.object({
path: z
.string()
.optional()
.describe("Path to list, relative to the working directory. Defaults to '.'"),
}),
execute: async (args: Record<string, unknown>): Promise<string> => {
const relPath = (args.path as string | undefined) ?? ".";
// Canonicalize so a symlink-in-workdir pointing outside is detected.
// See `canonicalize` in ./path-utils.ts for the resolution semantics.
const absolutePath = await canonicalize(workingDirectory, relPath);
const absoluteWorkDir = await canonicalize(workingDirectory);
if (absolutePath !== absoluteWorkDir && !absolutePath.startsWith(`${absoluteWorkDir}/`)) {
return `Error: Path "${relPath}" is outside the working directory.`;
}
try {
const entries = await readdir(absolutePath, { withFileTypes: true });
if (entries.length === 0) {
return "(empty directory)";
}
return entries
.map((entry) => (entry.isDirectory() ? `${entry.name}/` : entry.name))
.join("\n");
} catch (err) {
return `Error listing files: ${err instanceof Error ? err.message : String(err)}`;
}
},
};
}
|