feat(opencode): fff search tools (#27802)

Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>
This commit is contained in:
Dmitriy Kovalenko
2026-06-06 06:42:31 -07:00
committed by GitHub
parent 4814ab3a3d
commit 7d3d80f840
28 changed files with 1256 additions and 138 deletions
@@ -2,6 +2,7 @@ import * as InstanceState from "@/effect/instance-state"
import { FileSystem } from "@opencode-ai/core/filesystem"
import { LocationServiceMap } from "@opencode-ai/core/location-layer"
import { Ripgrep } from "@opencode-ai/core/filesystem/ripgrep"
import { Search } from "@opencode-ai/core/filesystem/search"
import { FSUtil } from "@opencode-ai/core/fs-util"
import { AbsolutePath, RelativePath } from "@opencode-ai/core/schema"
import { Effect, Layer } from "effect"
@@ -12,6 +13,7 @@ import { InstanceHttpApi } from "../api"
export const fileHandlers = HttpApiBuilder.group(InstanceHttpApi, "file", (handlers) =>
Effect.gen(function* () {
const ripgrep = yield* Ripgrep.Service
const search = yield* Search.Service
const locations = yield* LocationServiceMap
const filesystem = Effect.fnUntraced(function* <A, E, R>(effect: Effect.Effect<A, E, R>) {
@@ -29,11 +31,18 @@ export const fileHandlers = HttpApiBuilder.group(InstanceHttpApi, "file", (handl
const findFile = Effect.fn("FileHttpApi.findFile")(function* (ctx: {
query: { query: string; dirs?: "true" | "false"; type?: "file" | "directory"; limit?: number }
}) {
const directory = (yield* InstanceState.context).directory
const limit = ctx.query.limit ?? 10
const kind = ctx.query.type ?? (ctx.query.dirs === "false" ? "file" : "all")
// Prefer fff (frecency + fuzzy ranking) and trust its ordering. Fall back
// to the ripgrep-backed FileSystem.find when fff is unavailable.
const fff = yield* search.file({ cwd: directory, query: ctx.query.query, limit, kind }).pipe(Effect.orDie)
if (fff !== undefined) return fff
return (yield* filesystem(
FileSystem.Service.use((fs) =>
fs.find({
query: ctx.query.query,
limit: ctx.query.limit ?? 10,
limit,
type: ctx.query.type ?? (ctx.query.dirs === "false" ? "file" : undefined),
}),
),
@@ -91,4 +100,4 @@ export const fileHandlers = HttpApiBuilder.group(InstanceHttpApi, "file", (handl
.handle("content", content)
.handle("status", status)
}),
).pipe(Layer.provide(LocationServiceMap.layer))
).pipe(Layer.provide(LocationServiceMap.layer), Layer.provide(Search.defaultLayer))