convert list tool to Tool.defineEffect (#21899)
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
import z from "zod"
|
import z from "zod"
|
||||||
|
import { Effect } from "effect"
|
||||||
|
import * as Stream from "effect/Stream"
|
||||||
import { Tool } from "./tool"
|
import { Tool } from "./tool"
|
||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import DESCRIPTION from "./ls.txt"
|
import DESCRIPTION from "./ls.txt"
|
||||||
import { Instance } from "../project/instance"
|
import { Instance } from "../project/instance"
|
||||||
import { Ripgrep } from "../file/ripgrep"
|
import { Ripgrep } from "../file/ripgrep"
|
||||||
import { assertExternalDirectory } from "./external-directory"
|
import { assertExternalDirectoryEffect } from "./external-directory"
|
||||||
|
|
||||||
export const IGNORE_PATTERNS = [
|
export const IGNORE_PATTERNS = [
|
||||||
"node_modules/",
|
"node_modules/",
|
||||||
@@ -35,31 +37,39 @@ export const IGNORE_PATTERNS = [
|
|||||||
|
|
||||||
const LIMIT = 100
|
const LIMIT = 100
|
||||||
|
|
||||||
export const ListTool = Tool.define("list", {
|
export const ListTool = Tool.defineEffect(
|
||||||
|
"list",
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const rg = yield* Ripgrep.Service
|
||||||
|
|
||||||
|
return {
|
||||||
description: DESCRIPTION,
|
description: DESCRIPTION,
|
||||||
parameters: z.object({
|
parameters: z.object({
|
||||||
path: z.string().describe("The absolute path to the directory to list (must be absolute, not relative)").optional(),
|
path: z.string().describe("The absolute path to the directory to list (must be absolute, not relative)").optional(),
|
||||||
ignore: z.array(z.string()).describe("List of glob patterns to ignore").optional(),
|
ignore: z.array(z.string()).describe("List of glob patterns to ignore").optional(),
|
||||||
}),
|
}),
|
||||||
async execute(params, ctx) {
|
execute: (params: { path?: string; ignore?: string[] }, ctx: Tool.Context) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
const searchPath = path.resolve(Instance.directory, params.path || ".")
|
const searchPath = path.resolve(Instance.directory, params.path || ".")
|
||||||
await assertExternalDirectory(ctx, searchPath, { kind: "directory" })
|
yield* assertExternalDirectoryEffect(ctx, searchPath, { kind: "directory" })
|
||||||
|
|
||||||
await ctx.ask({
|
yield* Effect.promise(() =>
|
||||||
|
ctx.ask({
|
||||||
permission: "list",
|
permission: "list",
|
||||||
patterns: [searchPath],
|
patterns: [searchPath],
|
||||||
always: ["*"],
|
always: ["*"],
|
||||||
metadata: {
|
metadata: {
|
||||||
path: searchPath,
|
path: searchPath,
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
const ignoreGlobs = IGNORE_PATTERNS.map((p) => `!${p}*`).concat(params.ignore?.map((p) => `!${p}`) || [])
|
const ignoreGlobs = IGNORE_PATTERNS.map((p) => `!${p}*`).concat(params.ignore?.map((p) => `!${p}`) || [])
|
||||||
const files = []
|
const files = yield* rg.files({ cwd: searchPath, glob: ignoreGlobs }).pipe(
|
||||||
for await (const file of Ripgrep.files({ cwd: searchPath, glob: ignoreGlobs, signal: ctx.abort })) {
|
Stream.take(LIMIT),
|
||||||
files.push(file)
|
Stream.runCollect,
|
||||||
if (files.length >= LIMIT) break
|
Effect.map((chunk) => [...chunk]),
|
||||||
}
|
)
|
||||||
|
|
||||||
// Build directory structure
|
// Build directory structure
|
||||||
const dirs = new Set<string>()
|
const dirs = new Set<string>()
|
||||||
@@ -117,5 +127,7 @@ export const ListTool = Tool.define("list", {
|
|||||||
},
|
},
|
||||||
output,
|
output,
|
||||||
}
|
}
|
||||||
},
|
}).pipe(Effect.orDie, Effect.runPromise),
|
||||||
})
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user