feat(core): improve read tool parity (#39126)

This commit is contained in:
Aiden Cline 2026-07-27 09:58:37 -05:00 committed by GitHub
commit 65d2a4e00c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 97 additions and 13 deletions

View file

@ -115,4 +115,21 @@ describe("ReadToolFileSystem", () => {
)
}),
)
it.effect("reads PDFs as bounded media", () =>
Effect.gen(function* () {
const { fs, files, directory } = yield* fixture
const file = path.join(directory, "document.pdf")
yield* files.writeFileString(file, "%PDF-1.7\ncontent")
const result = yield* ReadToolFileSystem.read(fs, file, "document.pdf")
expect(result).toMatchObject({
type: "file",
content: Buffer.from("%PDF-1.7\ncontent").toString("base64"),
encoding: "base64",
mime: "application/pdf",
})
}),
)
})

View file

@ -540,6 +540,35 @@ describe("ReadTool", () => {
}),
)
it.effect("returns PDFs as native media", () =>
Effect.gen(function* () {
const pdf = "JVBERi0xLjcK"
readResult = {
type: "file",
uri: "file:///document.pdf",
name: "document.pdf",
content: pdf,
encoding: "base64",
mime: "application/pdf",
}
const registry = yield* Tool.Service
expect(
yield* executeTool(registry, {
sessionID,
...toolIdentity,
call: { type: "tool-call", id: "call-pdf", name: "read", input: { path: "document.pdf" } },
}),
).toMatchObject({
status: "completed",
content: [
{ type: "text", text: "PDF read successfully" },
{ type: "file", uri: `data:application/pdf;base64,${pdf}`, mime: "application/pdf", name: "document.pdf" },
],
})
}),
)
it.effect("returns expected filesystem failures to the model", () =>
Effect.gen(function* () {
readFailure = new ReadToolFileSystem.BinaryFileError({ resource: "archive.dat" })
@ -563,6 +592,32 @@ describe("ReadTool", () => {
}),
)
it.effect("preserves actionable read failure messages", () =>
Effect.gen(function* () {
const registry = yield* Tool.Service
for (const [error, message] of [
[
new ReadToolFileSystem.MalformedUtf8Error({ resource: "invalid.txt" }),
"File is not valid UTF-8: invalid.txt",
],
[new ReadToolFileSystem.OffsetOutOfRangeError({ offset: 10 }), "Offset 10 is out of range"],
[
new ReadToolFileSystem.PathKindError({ resource: "socket", expected: "a file" }),
"Path is not a file: socket",
],
] as const) {
readFailure = error
expect(
yield* executeTool(registry, {
sessionID,
...toolIdentity,
call: { type: "tool-call", id: `call-${error._tag}`, name: "read", input: { path: "target" } },
}),
).toEqual({ status: "error", error: { type: "unknown", message } })
}
}),
)
it.effect("preserves unexpected filesystem defects", () =>
Effect.gen(function* () {
resolveFailure = new Error("unexpected")