tweak: ensure read tool uses fs/promises for all paths (#14027)

This commit is contained in:
Aiden Cline
2026-02-17 16:05:22 -06:00
committed by GitHub
parent cb88fe26aa
commit 3b97580621

View File

@@ -1,5 +1,6 @@
import z from "zod" import z from "zod"
import * as fs from "fs" import { createReadStream } from "fs"
import * as fs from "fs/promises"
import * as path from "path" import * as path from "path"
import { createInterface } from "readline" import { createInterface } from "readline"
import { Tool } from "./tool" import { Tool } from "./tool"
@@ -52,14 +53,18 @@ export const ReadTool = Tool.define("read", {
const dir = path.dirname(filepath) const dir = path.dirname(filepath)
const base = path.basename(filepath) const base = path.basename(filepath)
const dirEntries = fs.readdirSync(dir) const suggestions = await fs
const suggestions = dirEntries .readdir(dir)
.filter( .then((entries) =>
(entry) => entries
entry.toLowerCase().includes(base.toLowerCase()) || base.toLowerCase().includes(entry.toLowerCase()), .filter(
(entry) =>
entry.toLowerCase().includes(base.toLowerCase()) || base.toLowerCase().includes(entry.toLowerCase()),
)
.map((entry) => path.join(dir, entry))
.slice(0, 3),
) )
.map((entry) => path.join(dir, entry)) .catch(() => [])
.slice(0, 3)
if (suggestions.length > 0) { if (suggestions.length > 0) {
throw new Error(`File not found: ${filepath}\n\nDid you mean one of these?\n${suggestions.join("\n")}`) throw new Error(`File not found: ${filepath}\n\nDid you mean one of these?\n${suggestions.join("\n")}`)
@@ -69,12 +74,12 @@ export const ReadTool = Tool.define("read", {
} }
if (stat.isDirectory()) { if (stat.isDirectory()) {
const dirents = await fs.promises.readdir(filepath, { withFileTypes: true }) const dirents = await fs.readdir(filepath, { withFileTypes: true })
const entries = await Promise.all( const entries = await Promise.all(
dirents.map(async (dirent) => { dirents.map(async (dirent) => {
if (dirent.isDirectory()) return dirent.name + "/" if (dirent.isDirectory()) return dirent.name + "/"
if (dirent.isSymbolicLink()) { if (dirent.isSymbolicLink()) {
const target = await fs.promises.stat(path.join(filepath, dirent.name)).catch(() => undefined) const target = await fs.stat(path.join(filepath, dirent.name)).catch(() => undefined)
if (target?.isDirectory()) return dirent.name + "/" if (target?.isDirectory()) return dirent.name + "/"
} }
return dirent.name return dirent.name
@@ -140,7 +145,7 @@ export const ReadTool = Tool.define("read", {
const isBinary = await isBinaryFile(filepath, stat.size) const isBinary = await isBinaryFile(filepath, stat.size)
if (isBinary) throw new Error(`Cannot read binary file: ${filepath}`) if (isBinary) throw new Error(`Cannot read binary file: ${filepath}`)
const stream = fs.createReadStream(filepath, { encoding: "utf8" }) const stream = createReadStream(filepath, { encoding: "utf8" })
const rl = createInterface({ const rl = createInterface({
input: stream, input: stream,
// Note: we use the crlfDelay option to recognize all instances of CR LF // Note: we use the crlfDelay option to recognize all instances of CR LF
@@ -267,7 +272,7 @@ async function isBinaryFile(filepath: string, fileSize: number): Promise<boolean
if (fileSize === 0) return false if (fileSize === 0) return false
const fh = await fs.promises.open(filepath, "r") const fh = await fs.open(filepath, "r")
try { try {
const sampleSize = Math.min(4096, fileSize) const sampleSize = Math.min(4096, fileSize)
const bytes = Buffer.alloc(sampleSize) const bytes = Buffer.alloc(sampleSize)