import { createReadStream } from "node:fs"; import { createInterface } from "node:readline"; import path from "node:path"; const virtual_chroot = '/workspaces/aiTools'; // Ensures reads are confined to `virtual_chroot`. export default { type: "function", name: "read_file", description: "read a file", strict: true, parameters: { type: "object", required: ["path","linesToSkip","linesToRead"], additionalProperties: false, properties: { path: { type: "string", description: "The path to the file to read.", }, linesToSkip: { type: "integer", description: "The number of lines to skip. Use 0 to read from the beginning.", minimum: 0 }, linesToRead: { type: "integer", description: "1-400 The number of lines to read. Use 0 or more than 400 to read 400 lines.", minimum: 0 } } } }; export async function run(args) { const { path: filePath, linesToSkip, linesToRead } = args; // Validate path is within virtual_chroot const fullPath = path.resolve(virtual_chroot, filePath.replace(/^\//, '')); if (!fullPath.startsWith(virtual_chroot)) { return `read_file error: Path outside of allowed directory`; } // Normalize linesToRead (1-400, with 0 or >400 meaning 400) const maxLines = (linesToRead <= 0 || linesToRead > 400) ? 400 : linesToRead; try { const rl = createInterface({ input: createReadStream(fullPath), crlfDelay: Infinity }); let lines = []; let skipped = 0; for await (const line of rl) { if (skipped < linesToSkip) { skipped++; continue; } lines.push(line); if (lines.length >= maxLines) { break; } } return lines.join('\n'); } catch (error) { return `read_file error: ${error.message}`; } }