From 732fb1b9457cbd2d5430496449007e654111fee9 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Wed, 22 Apr 2026 22:18:22 +0530 Subject: [PATCH] build(search): add fff-bun runtime shims --- bun.lock | 45 ++++++++++++++ packages/opencode/package.json | 6 ++ packages/opencode/src/file/fff.bun.ts | 85 ++++++++++++++++++++++++++ packages/opencode/src/file/fff.node.ts | 85 ++++++++++++++++++++++++++ 4 files changed, 221 insertions(+) create mode 100644 packages/opencode/src/file/fff.bun.ts create mode 100644 packages/opencode/src/file/fff.node.ts diff --git a/bun.lock b/bun.lock index 64b32feac..d867ef674 100644 --- a/bun.lock +++ b/bun.lock @@ -346,6 +346,7 @@ "@clack/prompts": "1.0.0-alpha.1", "@effect/opentelemetry": "catalog:", "@effect/platform-node": "catalog:", + "@ff-labs/fff-bun": "0.6.1", "@gitlab/opencode-gitlab-auth": "1.3.3", "@hono/node-server": "1.19.11", "@hono/node-ws": "1.3.0", @@ -1184,6 +1185,24 @@ "@fastify/rate-limit": ["@fastify/rate-limit@10.3.0", "", { "dependencies": { "@lukeed/ms": "^2.0.2", "fastify-plugin": "^5.0.0", "toad-cache": "^3.7.0" } }, "sha512-eIGkG9XKQs0nyynatApA3EVrojHOuq4l6fhB4eeCk4PIOeadvOJz9/4w3vGI44Go17uaXOWEcPkaD8kuKm7g6Q=="], + "@ff-labs/fff-bin-darwin-arm64": ["@ff-labs/fff-bin-darwin-arm64@0.6.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-l9e19O3oFrJboSNRYQcgEEXFhOItxv/rkLxqSqXpbc16iewn4d5lPnv4yBD9qnPo8CcnmSJHDIY8s7Z5VhDRCQ=="], + + "@ff-labs/fff-bin-darwin-x64": ["@ff-labs/fff-bin-darwin-x64@0.6.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cb4JIfqC2zIRNbSZe/rc4ypT4Y7UiBsJ8/i8Ak1k8UWqpoYZ6tSOXgct6P9tgLDPtRU8pozV+8+n5U3g86yK7g=="], + + "@ff-labs/fff-bin-linux-arm64-gnu": ["@ff-labs/fff-bin-linux-arm64-gnu@0.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-c86ybRKMLczxq5DxNs+UrxeQIyUBOX5aoTPvpfbh6bRL3lCJLA5JZNHLSUNUsdklhp2YMmDs5Aj1kTwb/nX/UQ=="], + + "@ff-labs/fff-bin-linux-arm64-musl": ["@ff-labs/fff-bin-linux-arm64-musl@0.6.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1AMfgovae7OoCy8e7wp50vMb053MyM8/Mtd+muRU8U3BmKHxnmbRuhl8oIPBBOHqK8WbJFeSxAv6iK7GIYRkFw=="], + + "@ff-labs/fff-bin-linux-x64-gnu": ["@ff-labs/fff-bin-linux-x64-gnu@0.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-q/cUHWfiJHg14SjJqVnu6nhPt/432R1lhUx99TKyb3vsqKS7+LP8S9kju7I4oEkJ23HxcnZ0muavCwapT+7R3Q=="], + + "@ff-labs/fff-bin-linux-x64-musl": ["@ff-labs/fff-bin-linux-x64-musl@0.6.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Yt0dtbOAiNrRzerlRAehonJ1abaOULoOenDrswToBUnUudMav86hxKNcWY3WntU7dFbRiZyGMhiGKse2qDmlGw=="], + + "@ff-labs/fff-bin-win32-arm64": ["@ff-labs/fff-bin-win32-arm64@0.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-pNE3VZ4noafA9cj5XyTSHY4k4I1q0EgflQFAPI/kC+R6gLl6ZB0meJ6at+PWmeKGzkg34t6zc+cbs4G5UJcCvA=="], + + "@ff-labs/fff-bin-win32-x64": ["@ff-labs/fff-bin-win32-x64@0.6.1", "", { "os": "win32", "cpu": "x64" }, "sha512-f8s/VCFUtMJsvLZCD6YWJRsUA13BxuxKTlPQ1RgF7y4V8ugC304Ic3xLfJApfs5mEixDeWinE7Hh3bJL4W9i2Q=="], + + "@ff-labs/fff-bun": ["@ff-labs/fff-bun@0.6.1", "", { "optionalDependencies": { "@ff-labs/fff-bin-darwin-arm64": "0.6.1", "@ff-labs/fff-bin-darwin-x64": "0.6.1", "@ff-labs/fff-bin-linux-arm64-gnu": "0.6.1", "@ff-labs/fff-bin-linux-arm64-musl": "0.6.1", "@ff-labs/fff-bin-linux-x64-gnu": "0.6.1", "@ff-labs/fff-bin-linux-x64-musl": "0.6.1", "@ff-labs/fff-bin-win32-arm64": "0.6.1", "@ff-labs/fff-bin-win32-x64": "0.6.1" }, "peerDependencies": { "bun": ">=1.0.0" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "fff-demo": "examples/search.ts", "fff-grep": "examples/grep.ts" } }, "sha512-J8O4gpkfKbcWsskMFxn979b0WzvRDb9im5WhBpsjKrXTMzQr7I4DxhstbtiwaUdli3G6eHTrAOw3oD89g+0P/A=="], + "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], @@ -1630,6 +1649,30 @@ "@oslojs/jwt": ["@oslojs/jwt@0.2.0", "", { "dependencies": { "@oslojs/encoding": "0.4.1" } }, "sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg=="], + "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-qAS6Hg8Q14ckfBuqJ2Zh7gBQSVSUHeibSq4OFqBTv6DzyJuxYlr0sdYQzmYmnbPxbqobekqUDTa/4XEaqRi7vg=="], + + "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-kGePeDD4IN4imo+H4uLjQGZLmvyYQg+nKr2P0nt4ksXXrWA4HE+mb0/TUPHfRI127DocXQpew+fvrHuHR5mpJQ=="], + + "@oven/bun-darwin-x64-baseline": ["@oven/bun-darwin-x64-baseline@1.3.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-gMEQayUpmCPYaE9zkNBj9TiQqHupnhjOYcuSzxFjzIjHJBUO4VjNnrpbKVeXNs+rKHFothORDd2QKquu5paSPQ=="], + + "@oven/bun-linux-aarch64": ["@oven/bun-linux-aarch64@1.3.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-NbLOJdr+RBFO1vFZ2YUFg4oVJ+2ua6zrwo4ZWRs0jKKcGJWtbY2wY5uz+i0PkwH6b9HYaYDgVTzE4ev06ncYZw=="], + + "@oven/bun-linux-aarch64-musl": ["@oven/bun-linux-aarch64-musl@1.3.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-UV9EE18VE5aRhWtV2L6MTAGGn3slhJJ2OW/m+FJM15maHm0qf1V7TaZY0FovxhdQRvnklSiQ7Ntv0H5TUX4w0g=="], + + "@oven/bun-linux-x64": ["@oven/bun-linux-x64@1.3.13", "", { "os": "linux", "cpu": "x64" }, "sha512-UwttIUXoe9fS+40OcjoaRHgZw+HCPFqBVWEXkXqAJ3W7wA0XPZrWsoMAD9sGh3TaLqrwdiMo5xPogwpXhOtVXA=="], + + "@oven/bun-linux-x64-baseline": ["@oven/bun-linux-x64-baseline@1.3.13", "", { "os": "linux", "cpu": "x64" }, "sha512-fOi4ziKzgJG4UrrNd4AicBs6Fu9GY5xOqg+9tC76nuZNDAdSh6++kzab6TNi1Ck0Yzq6zIBIdGit6/0uSbBn8A=="], + + "@oven/bun-linux-x64-musl": ["@oven/bun-linux-x64-musl@1.3.13", "", { "os": "linux", "cpu": "x64" }, "sha512-+VHhE44kEjCXcTFHyc81zfTxL9+vzh9RqIh7gM1iWNhxpctD9kzntbUkP3UTFTwwNjoou1o8VRyxQafvc4OepA=="], + + "@oven/bun-linux-x64-musl-baseline": ["@oven/bun-linux-x64-musl-baseline@1.3.13", "", { "os": "linux", "cpu": "x64" }, "sha512-fqBKuiiWLEu2dVkowZaXgKS98xfrvBqivdoxRtRP3eINcpI1dcelGbsOz+Xphn7tbGAuBiE1/0AelvvvdqS9rg=="], + + "@oven/bun-windows-aarch64": ["@oven/bun-windows-aarch64@1.3.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-+EvdRWRCRg95Xea4M2lqSJFTjzQBTJDQTMlbG8bmwFkVTN16MdmSH7xhfxVQWUOyZBLEpIwuNFIlBBxVCwSUyQ=="], + + "@oven/bun-windows-x64": ["@oven/bun-windows-x64@1.3.13", "", { "os": "win32", "cpu": "x64" }, "sha512-vqDEFX63ZZQF3YstPSpPD+RxNm5AILPdUuuKpNwsj7ld4NjhdHUYkAmLXDtKNWt9JMRL10bop//W8faY/LV+RQ=="], + + "@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.13", "", { "os": "win32", "cpu": "x64" }, "sha512-6gy4hhQSjq/T/S9hC9m3NxY0RY+9Ww+XNlB+8koIMTsMSYEjk7Ho+hFHQz1Bn4W61Ub7Vykufg+jgDgPfa2GFA=="], + "@oxc-minify/binding-android-arm64": ["@oxc-minify/binding-android-arm64@0.96.0", "", { "os": "android", "cpu": "arm64" }, "sha512-lzeIEMu/v6Y+La5JSesq4hvyKtKBq84cgQpKYTYM/yGuNk2tfd5Ha31hnC+mTh48lp/5vZH+WBfjVUjjINCfug=="], "@oxc-minify/binding-darwin-arm64": ["@oxc-minify/binding-darwin-arm64@0.96.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-i0LkJAUXb4BeBFrJQbMKQPoxf8+cFEffDyLSb7NEzzKuPcH8qrVsnEItoOzeAdYam8Sr6qCHVwmBNEQzl7PWpw=="], @@ -2716,6 +2759,8 @@ "builder-util-runtime": ["builder-util-runtime@9.5.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ=="], + "bun": ["bun@1.3.13", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.13", "@oven/bun-darwin-x64": "1.3.13", "@oven/bun-darwin-x64-baseline": "1.3.13", "@oven/bun-linux-aarch64": "1.3.13", "@oven/bun-linux-aarch64-musl": "1.3.13", "@oven/bun-linux-x64": "1.3.13", "@oven/bun-linux-x64-baseline": "1.3.13", "@oven/bun-linux-x64-musl": "1.3.13", "@oven/bun-linux-x64-musl-baseline": "1.3.13", "@oven/bun-windows-aarch64": "1.3.13", "@oven/bun-windows-x64": "1.3.13", "@oven/bun-windows-x64-baseline": "1.3.13" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-b9T4xZ8KqCHs4+TkHJv540LG1B8OD7noKu0Qaizusx3jFtMDHY6osNqgbaOlwW2B8RB2AKzz+sjzlGKIGxIjZw=="], + "bun-ffi-structs": ["bun-ffi-structs@0.1.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-Lh1oQAYHDcnesJauieA4UNkWGXY9hYck7OA5IaRwE3Bp6K2F2pJSNYqq+hIy7P3uOvo3km3oxS8304g5gDMl/w=="], "bun-pty": ["bun-pty@0.4.8", "", {}, "sha512-rO70Mrbr13+jxHHHu2YBkk2pNqrJE5cJn29WE++PUr+GFA0hq/VgtQPZANJ8dJo6d7XImvBk37Innt8GM7O28w=="], diff --git a/packages/opencode/package.json b/packages/opencode/package.json index dcd0a9ad6..10772878b 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -29,6 +29,11 @@ "node": "./src/storage/db.node.ts", "default": "./src/storage/db.bun.ts" }, + "#fff": { + "bun": "./src/file/fff.bun.ts", + "node": "./src/file/fff.node.ts", + "default": "./src/file/fff.bun.ts" + }, "#pty": { "bun": "./src/pty/pty.bun.ts", "node": "./src/pty/pty.node.ts", @@ -102,6 +107,7 @@ "@clack/prompts": "1.0.0-alpha.1", "@effect/opentelemetry": "catalog:", "@effect/platform-node": "catalog:", + "@ff-labs/fff-bun": "0.6.1", "@gitlab/opencode-gitlab-auth": "1.3.3", "@hono/node-server": "1.19.11", "@hono/node-ws": "1.3.0", diff --git a/packages/opencode/src/file/fff.bun.ts b/packages/opencode/src/file/fff.bun.ts new file mode 100644 index 000000000..f278eec46 --- /dev/null +++ b/packages/opencode/src/file/fff.bun.ts @@ -0,0 +1,85 @@ +import { + FileFinder, + type FileItem, + type GrepCursor, + type GrepMatch, + type GrepResult, + type InitOptions, + type SearchResult, +} from "@ff-labs/fff-bun" + +export type Result = { ok: true; value: T } | { ok: false; error: string } + +export type Init = InitOptions + +export interface Search { + items: FileItem[] + scores: SearchResult["scores"] + totalMatched: number + totalFiles: number +} + +export type File = FileItem +export type Cursor = GrepCursor | null +export type Hit = GrepMatch + +export interface Grep { + items: GrepResult["items"] + totalMatched: number + totalFilesSearched: number + totalFiles: number + filteredFileCount: number + nextCursor: Cursor + regexFallbackError?: string +} + +export interface Picker { + destroy(): void + waitForScan(timeout?: number): Result + refreshGitStatus(): Result + fileSearch( + query: string, + opts?: { + currentFile?: string + pageIndex?: number + pageSize?: number + }, + ): Result + grep( + query: string, + opts?: { + mode?: "plain" | "regex" | "fuzzy" + maxMatchesPerFile?: number + timeBudgetMs?: number + beforeContext?: number + afterContext?: number + cursor?: Cursor + }, + ): Result + trackQuery(query: string, file: string): Result + getHistoricalQuery(offset: number): Result +} + +export function available() { + return FileFinder.isAvailable() +} + +export function create(opts: Init): Result { + const made = FileFinder.create(opts) + if (!made.ok) return made + const pick = made.value + return { + ok: true, + value: { + destroy: () => pick.destroy(), + waitForScan: (timeout) => pick.waitForScan(timeout), + refreshGitStatus: () => pick.refreshGitStatus(), + fileSearch: (query, next) => pick.fileSearch(query, next), + grep: (query, next) => pick.grep(query, next), + trackQuery: (query, file) => pick.trackQuery(query, file), + getHistoricalQuery: (offset) => pick.getHistoricalQuery(offset), + }, + } +} + +export * as Fff from "./fff.bun" diff --git a/packages/opencode/src/file/fff.node.ts b/packages/opencode/src/file/fff.node.ts new file mode 100644 index 000000000..9edf2052d --- /dev/null +++ b/packages/opencode/src/file/fff.node.ts @@ -0,0 +1,85 @@ +export type Result = { ok: true; value: T } | { ok: false; error: string } + +export interface Init { + basePath: string + frecencyDbPath?: string + historyDbPath?: string + useUnsafeNoLock?: boolean + disableMmapCache?: boolean + disableContentIndexing?: boolean + disableWatch?: boolean + aiMode?: boolean +} + +export interface File { + relativePath: string + fileName: string + modified: number +} + +export interface Search { + items: File[] + scores: unknown[] + totalMatched: number + totalFiles: number +} + +export type Cursor = null + +export interface Hit { + relativePath: string + fileName: string + lineNumber: number + byteOffset: number + lineContent: string + matchRanges: [number, number][] + contextBefore?: string[] + contextAfter?: string[] +} + +export interface Grep { + items: Hit[] + totalMatched: number + totalFilesSearched: number + totalFiles: number + filteredFileCount: number + nextCursor: Cursor + regexFallbackError?: string +} + +export interface Picker { + destroy(): void + waitForScan(timeout?: number): Result + refreshGitStatus(): Result + fileSearch( + query: string, + opts?: { + currentFile?: string + pageIndex?: number + pageSize?: number + }, + ): Result + grep( + query: string, + opts?: { + mode?: "plain" | "regex" | "fuzzy" + maxMatchesPerFile?: number + timeBudgetMs?: number + beforeContext?: number + afterContext?: number + cursor?: Cursor + }, + ): Result + trackQuery(query: string, file: string): Result + getHistoricalQuery(offset: number): Result +} + +export function available() { + return false +} + +export function create(_opts: Init): Result { + return { ok: false, error: "fff unavailable" } +} + +export * as Fff from "./fff.node"