refactor(effect): move read tool onto defineEffect

pull/21016/head
Kit Langton 2026-04-02 22:54:01 -04:00
parent 288eb044cb
commit 62f1421120
2 changed files with 214 additions and 194 deletions

View File

@ -1,4 +1,5 @@
import z from "zod"
import { Effect } from "effect"
import { createReadStream } from "fs"
import * as fs from "fs/promises"
import * as path from "path"
@ -18,14 +19,18 @@ const MAX_LINE_SUFFIX = `... (line truncated to ${MAX_LINE_LENGTH} chars)`
const MAX_BYTES = 50 * 1024
const MAX_BYTES_LABEL = `${MAX_BYTES / 1024} KB`
export const ReadTool = Tool.define("read", {
description: DESCRIPTION,
parameters: z.object({
const parameters = z.object({
filePath: z.string().describe("The absolute path to the file or directory to read"),
offset: z.coerce.number().describe("The line number to start reading from (1-indexed)").optional(),
limit: z.coerce.number().describe("The maximum number of lines to read (defaults to 2000)").optional(),
}),
async execute(params, ctx) {
})
export const ReadTool = Tool.defineEffect(
"read",
Effect.succeed({
description: DESCRIPTION,
parameters,
async execute(params: z.infer<typeof parameters>, ctx) {
if (params.offset !== undefined && params.offset < 1) {
throw new Error("offset must be greater than or equal to 1")
}
@ -216,7 +221,7 @@ export const ReadTool = Tool.define("read", {
output += "\n</content>"
// just warms the lsp client
LSP.touchFile(filepath, false)
await LSP.touchFile(filepath, false)
await FileTime.read(ctx.sessionID, filepath)
if (instructions.length > 0) {
@ -233,7 +238,8 @@ export const ReadTool = Tool.define("read", {
},
}
},
})
}),
)
async function isBinaryFile(filepath: string, fileSize: number): Promise<boolean> {
const ext = path.extname(filepath).toLowerCase()

View File

@ -1,7 +1,9 @@
import { afterEach, describe, expect, test } from "bun:test"
import { Effect } from "effect"
import path from "path"
import { ReadTool } from "../../src/tool/read"
import { Instance } from "../../src/project/instance"
import { ReadTool as ReadToolFx } from "../../src/tool/read"
import { Tool } from "../../src/tool/tool"
import { Filesystem } from "../../src/util/filesystem"
import { tmpdir } from "../fixture/fixture"
import { Permission } from "../../src/permission"
@ -25,6 +27,18 @@ const ctx = {
ask: async () => {},
}
const ReadTool = {
init: async () => ({
execute: (args: Tool.InferParameters<typeof ReadToolFx>, ctx: Tool.Context) =>
Effect.runPromise(
ReadToolFx.pipe(
Effect.flatMap((tool) => Effect.promise(() => tool.init())),
Effect.flatMap((tool) => Effect.promise(() => tool.execute(args, ctx))),
),
),
}),
}
const full = (p: string) => (process.platform === "win32" ? Filesystem.normalizePath(p) : p)
const glob = (p: string) =>
process.platform === "win32" ? Filesystem.normalizePathPattern(p) : p.replaceAll("\\", "/")