refactor(core): unify filesystem search service (#31566)

This commit is contained in:
Dax 2026-06-09 20:38:02 -04:00 committed by GitHub
commit a0409e64d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 962 additions and 2852 deletions

View file

@ -1,10 +1,11 @@
import { Effect } from "effect"
import { Fff } from "@opencode-ai/core/filesystem/fff.bun"
import { AppRuntime } from "@/effect/app-runtime"
import { Search } from "@opencode-ai/core/filesystem/search"
import { FileSystem } from "@opencode-ai/core/filesystem"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { InstanceStore } from "@/project/instance-store"
const dir = process.cwd()
const dir = AbsolutePath.make(process.cwd())
const FILE_QUERIES = ["fff", "package.json", "tools/ experiment"]
const GREP_QUERIES = ["FileFinder", "import", "grep", "autocomplete"]
@ -14,7 +15,7 @@ const FILE_LIMIT = 100
const GREP_LIMIT = 50
const GLOB_LIMIT = 50
const run = <A>(effect: Effect.Effect<A, unknown, Search.Service>) =>
const run = <A, R>(effect: Effect.Effect<A, unknown, R>) =>
AppRuntime.runPromise(
InstanceStore.Service.use((store) => store.provide({ directory: dir }, effect as never)),
) as Promise<A>
@ -57,32 +58,16 @@ for (const q of GREP_QUERIES) {
picker.destroy()
// --- Ripgrep service (via Search with file:["."] to force rg path) ---
console.log()
console.log("--- Ripgrep (via Search service) ---")
// warmup
await run(Search.Service.use((svc) => svc.search({ cwd: dir, pattern: "_warmup_rg_", limit: 1, file: ["."] })))
for (const q of GREP_QUERIES) {
const t = performance.now()
const r = await run(Search.Service.use((svc) => svc.search({ cwd: dir, pattern: q, limit: GREP_LIMIT, file: ["."] })))
console.log(
`[ripgrep] grep "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.items.length} total, limit is per-file not total)`,
)
}
// --- Search service: init breakdown ---
console.log()
// 1) runtime + InstanceState + picker create + scan poll
const tRuntime = performance.now()
await run(Search.Service.use((svc) => svc.file({ cwd: dir, query: "_warmup_file_", limit: 1 })))
console.log(`[Search] init file (runtime + picker + scan): ${(performance.now() - tRuntime).toFixed(1)}ms`)
// 2) grep warmup (content index cold-start inside the Search service picker)
const tGrepWarmup = performance.now()
await run(Search.Service.use((svc) => svc.search({ cwd: dir, pattern: "_warmup_grep_", limit: 1 })))
await run(FileSystem.Service.use((svc) => svc.grep({ pattern: "_warmup_grep_", limit: 1 })))
console.log(`[Search] init grep (content index warmup): ${(performance.now() - tGrepWarmup).toFixed(1)}ms`)
console.log()
@ -90,24 +75,20 @@ console.log("--- Search service (warm) ---")
for (const q of FILE_QUERIES) {
const t = performance.now()
const r = await run(Search.Service.use((svc) => svc.file({ cwd: dir, query: q, limit: FILE_LIMIT })))
console.log(`[Search.file] "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.length} results)`)
const r = await run(FileSystem.Service.use((svc) => svc.find({ query: q, limit: FILE_LIMIT })))
console.log(`[Search.find] "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.length} results)`)
}
for (const q of GREP_QUERIES) {
const t = performance.now()
const r = await run(Search.Service.use((svc) => svc.search({ cwd: dir, pattern: q, limit: GREP_LIMIT })))
console.log(
`[Search.search] "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.items.length} matches, engine=${r.engine})`,
)
const r = await run(FileSystem.Service.use((svc) => svc.grep({ pattern: q, limit: GREP_LIMIT })))
console.log(`[Search.grep] "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.length} matches)`)
}
for (const q of GLOB_QUERIES) {
const t = performance.now()
const r = await run(Search.Service.use((svc) => svc.glob({ cwd: dir, pattern: q, limit: GLOB_LIMIT })))
console.log(
`[Search.glob] "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.files.length} files, truncated=${r.truncated})`,
)
const r = await run(FileSystem.Service.use((svc) => svc.glob({ pattern: q, limit: GLOB_LIMIT })))
console.log(`[Search.glob] "${q}": ${(performance.now() - t).toFixed(1)}ms (${r.length} files)`)
}
process.exit(0)

View file

@ -140,6 +140,7 @@ const binaries: Record<string, string> = {}
if (!skipInstall) {
await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`
await $`bun install --os="*" --cpu="*" @parcel/watcher@${pkg.dependencies["@parcel/watcher"]}`
await $`bun install --os="*" --cpu="*" @ff-labs/fff-bun@${pkg.dependencies["@ff-labs/fff-bun"]}`
}
for (const item of targets) {
const name = [
@ -165,7 +166,7 @@ for (const item of targets) {
const workerRelativePath = path.relative(dir, parserWorker).replaceAll("\\", "/")
await Bun.build({
conditions: ["node"],
conditions: ["bun", "node"],
tsconfig: "./tsconfig.json",
plugins: [plugin],
external: ["node-gyp"],
@ -186,6 +187,7 @@ for (const item of targets) {
files: embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {},
entrypoints: ["./src/index.ts", parserWorker, workerPath, ...(embeddedFileMap ? ["opencode-web-ui.gen.ts"] : [])],
define: {
FFF_LIBC: JSON.stringify(item.abi === "musl" ? "musl" : "gnu"),
OPENCODE_VERSION: `'${Script.version}'`,
OPENCODE_MODELS_DEV: generated.modelsData,
OTUI_TREE_SITTER_WORKER_PATH: bunfsRoot + workerRelativePath,