Просмотр исходного кода

Refactor external tools organization and add file search API endpoint

🤖 Generated with [OpenCode](https://opencode.ai)

Co-Authored-By: OpenCode <[email protected]>
Dax Raad 8 месяцев назад
Родитель
Сommit
f6ed59bf45

+ 5 - 2
packages/opencode/src/ripgrep/index.ts → packages/opencode/src/external/ripgrep.ts

@@ -4,6 +4,7 @@ import { Global } from "../global"
 import fs from "fs/promises"
 import fs from "fs/promises"
 import { z } from "zod"
 import { z } from "zod"
 import { NamedError } from "../util/error"
 import { NamedError } from "../util/error"
+import { lazy } from "../util/lazy"
 
 
 export namespace Ripgrep {
 export namespace Ripgrep {
   const PLATFORM = {
   const PLATFORM = {
@@ -35,8 +36,10 @@ export namespace Ripgrep {
     }),
     }),
   )
   )
 
 
-  const state = App.state("ripgrep", async () => {
-    const filepath = path.join(
+  const state = lazy(async () => {
+    let filepath = Bun.which("rg")
+    if (filepath) return { filepath }
+    filepath = path.join(
       Global.Path.bin,
       Global.Path.bin,
       "rg" + (process.platform === "win32" ? ".exe" : ""),
       "rg" + (process.platform === "win32" ? ".exe" : ""),
     )
     )

+ 1 - 1
packages/opencode/src/file/index.ts

@@ -1,6 +1,6 @@
 export namespace File {
 export namespace File {
   const glob = new Bun.Glob("**/*")
   const glob = new Bun.Glob("**/*")
-  export async function search(path: string) {
+  export async function search(path: string, query: string) {
     for await (const entry of glob.scan({
     for await (const entry of glob.scan({
       cwd: path,
       cwd: path,
       onlyFiles: true,
       onlyFiles: true,

+ 1 - 1
packages/opencode/src/index.ts

@@ -26,7 +26,7 @@ const cli = yargs(hideBin(process.argv))
     describe: "Print logs to stderr",
     describe: "Print logs to stderr",
     type: "boolean",
     type: "boolean",
   })
   })
-  .middleware(async (args) => {
+  .middleware(async () => {
     await Log.init({ print: process.argv.includes("--print-logs") })
     await Log.init({ print: process.argv.includes("--print-logs") })
     Log.Default.info("opencode", {
     Log.Default.info("opencode", {
       version: VERSION,
       version: VERSION,

+ 29 - 0
packages/opencode/src/server/server.ts

@@ -12,6 +12,7 @@ import { App } from "../app/app"
 import { Global } from "../global"
 import { Global } from "../global"
 import { mapValues } from "remeda"
 import { mapValues } from "remeda"
 import { NamedError } from "../util/error"
 import { NamedError } from "../util/error"
+import { Fzf } from "../external/fzf"
 
 
 const ERRORS = {
 const ERRORS = {
   400: {
   400: {
@@ -427,6 +428,34 @@ export namespace Server {
           })
           })
         },
         },
       )
       )
+      .post(
+        "/file_search",
+        describeRoute({
+          description: "Search for files",
+          responses: {
+            200: {
+              description: "Search for files",
+              content: {
+                "application/json": {
+                  schema: resolver(z.string().array()),
+                },
+              },
+            },
+          },
+        }),
+        zValidator(
+          "json",
+          z.object({
+            query: z.string(),
+          }),
+        ),
+        async (c) => {
+          const body = c.req.valid("json")
+          const app = App.info()
+          const result = await Fzf.search(app.path.cwd, body.query)
+          return c.json(result)
+        },
+      )
 
 
     return result
     return result
   }
   }

+ 1 - 1
packages/opencode/src/tool/grep.ts

@@ -1,7 +1,7 @@
 import { z } from "zod"
 import { z } from "zod"
 import { Tool } from "./tool"
 import { Tool } from "./tool"
 import { App } from "../app/app"
 import { App } from "../app/app"
-import { Ripgrep } from "../ripgrep"
+import { Ripgrep } from "../external/ripgrep"
 
 
 import DESCRIPTION from "./grep.txt"
 import DESCRIPTION from "./grep.txt"
 
 

+ 11 - 0
packages/opencode/src/util/lazy.ts

@@ -0,0 +1,11 @@
+export function lazy<T>(fn: () => T) {
+  let value: T | undefined
+  let loaded = false
+
+  return (): T => {
+    if (loaded) return value as T
+    value = fn()
+    return value as T
+  }
+}
+