refactor(core): unify filesystem search service (#31566)
This commit is contained in:
@@ -2,13 +2,11 @@ import path from "path"
|
||||
import { Effect, Schema } from "effect"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
import { FSUtil } from "@opencode-ai/core/fs-util"
|
||||
import { Search } from "@opencode-ai/core/filesystem/search"
|
||||
import { Ripgrep } from "@opencode-ai/core/ripgrep"
|
||||
import { assertExternalDirectoryEffect } from "./external-directory"
|
||||
import DESCRIPTION from "./grep.txt"
|
||||
import * as Tool from "./tool"
|
||||
|
||||
const MAX_LINE_LENGTH = 2000
|
||||
|
||||
export const Parameters = Schema.Struct({
|
||||
pattern: Schema.String.annotate({ description: "The regex pattern to search for in file contents" }),
|
||||
path: Schema.optional(Schema.String).annotate({
|
||||
@@ -23,8 +21,7 @@ export const GrepTool = Tool.define(
|
||||
"grep",
|
||||
Effect.gen(function* () {
|
||||
const fs = yield* FSUtil.Service
|
||||
const searchSvc = yield* Search.Service
|
||||
|
||||
const ripgrep = yield* Ripgrep.Service
|
||||
return {
|
||||
description: DESCRIPTION,
|
||||
parameters: Parameters,
|
||||
@@ -63,30 +60,27 @@ export const GrepTool = Tool.define(
|
||||
const search = FSUtil.resolve(requested)
|
||||
const info = yield* fs.stat(search).pipe(Effect.catch(() => Effect.succeed(undefined)))
|
||||
const cwd = info?.type === "Directory" ? search : path.dirname(search)
|
||||
const file = info?.type === "Directory" ? undefined : [path.relative(cwd, search)]
|
||||
|
||||
const result = yield* searchSvc.search({
|
||||
const result = yield* ripgrep.grep({
|
||||
cwd,
|
||||
pattern: params.pattern,
|
||||
glob: params.include ? [params.include] : undefined,
|
||||
file,
|
||||
signal: ctx.abort,
|
||||
include: params.include,
|
||||
limit: 100,
|
||||
})
|
||||
if (result.items.length === 0) return empty
|
||||
if (result.length === 0) return empty
|
||||
|
||||
const rows = result.items.map((item) => ({
|
||||
path: FSUtil.resolve(path.isAbsolute(item.path.text) ? item.path.text : path.join(cwd, item.path.text)),
|
||||
line: item.line_number,
|
||||
text: item.lines.text,
|
||||
const rows = result.map((item) => ({
|
||||
path: path.resolve(cwd, item.entry.path),
|
||||
line: item.line,
|
||||
text: item.text,
|
||||
}))
|
||||
|
||||
const limit = 100
|
||||
const truncated = rows.length > limit
|
||||
const final = truncated ? rows.slice(0, limit) : rows
|
||||
const truncated = rows.length === limit
|
||||
const final = rows
|
||||
if (final.length === 0) return empty
|
||||
|
||||
const total = rows.length
|
||||
const hasMore = truncated || result.hasNextPage
|
||||
const hasMore = truncated || result.length === limit
|
||||
const output = [`Found ${total} matches${hasMore ? " (more matches available)" : ""}`]
|
||||
|
||||
let current = ""
|
||||
@@ -96,31 +90,12 @@ export const GrepTool = Tool.define(
|
||||
current = match.path
|
||||
output.push(`${match.path}:`)
|
||||
}
|
||||
const text =
|
||||
match.text.length > MAX_LINE_LENGTH ? match.text.substring(0, MAX_LINE_LENGTH) + "..." : match.text
|
||||
output.push(` Line ${match.line}: ${text}`)
|
||||
output.push(` Line ${match.line}: ${match.text}`)
|
||||
}
|
||||
|
||||
if (truncated) {
|
||||
output.push("")
|
||||
output.push(
|
||||
`(Results truncated: showing ${limit} of ${total} matches (${total - limit} hidden). Consider using a more specific path or pattern.)`,
|
||||
)
|
||||
}
|
||||
|
||||
if (result.hasNextPage) {
|
||||
output.push("")
|
||||
output.push(`(Results truncated. Consider using a more specific path or pattern.)`)
|
||||
}
|
||||
|
||||
if (result.partial) {
|
||||
output.push("")
|
||||
output.push("(Some paths were inaccessible and skipped)")
|
||||
}
|
||||
|
||||
if (result.regexFallbackError) {
|
||||
output.push("")
|
||||
output.push(`(Regex fallback: ${result.regexFallbackError})`)
|
||||
output.push("(Results truncated. Consider using a more specific path or pattern.)")
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user