Explorar o código

use forkScoped + Fiber.join for lazy init (match old Instance.state behavior)

Kit Langton hai 5 meses
pai
achega
1af7d26a86
Modificáronse 1 ficheiros con 29 adicións e 19 borrados
  1. 29 19
      packages/opencode/src/tool/registry.ts

+ 29 - 19
packages/opencode/src/tool/registry.ts

@@ -30,7 +30,7 @@ import { Truncate } from "./truncate"
 import { ApplyPatchTool } from "./apply_patch"
 import { Glob } from "../util/glob"
 import { pathToFileURL } from "url"
-import { Effect, Layer, ServiceMap } from "effect"
+import { Effect, Fiber, Layer, ServiceMap } from "effect"
 import { InstanceContext } from "@/effect/instance-context"
 import { runPromiseInstance } from "@/effect/runtime"
 
@@ -55,29 +55,36 @@ export namespace ToolRegistry {
 
       const custom: Tool.Info[] = []
 
-      yield* Effect.promise(async () => {
-        const matches = await Config.directories().then((dirs) =>
-          dirs.flatMap((dir) =>
-            Glob.scanSync("{tool,tools}/*.{js,ts}", { cwd: dir, absolute: true, dot: true, symlink: true }),
-          ),
-        )
-        if (matches.length) await Config.waitForDependencies()
-        for (const match of matches) {
-          const namespace = path.basename(match, path.extname(match))
-          const mod = await import(pathToFileURL(match).href)
-          for (const [id, def] of Object.entries<ToolDefinition>(mod)) {
-            custom.push(fromPlugin(id === "default" ? namespace : `${namespace}_${id}`, def))
+      const load = Effect.fn("ToolRegistry.load")(function* () {
+        yield* Effect.promise(async () => {
+          const matches = await Config.directories().then((dirs) =>
+            dirs.flatMap((dir) =>
+              Glob.scanSync("{tool,tools}/*.{js,ts}", { cwd: dir, absolute: true, dot: true, symlink: true }),
+            ),
+          )
+          if (matches.length) await Config.waitForDependencies()
+          for (const match of matches) {
+            const namespace = path.basename(match, path.extname(match))
+            const mod = await import(pathToFileURL(match).href)
+            for (const [id, def] of Object.entries<ToolDefinition>(mod)) {
+              custom.push(fromPlugin(id === "default" ? namespace : `${namespace}_${id}`, def))
+            }
           }
-        }
 
-        const plugins = await Plugin.list()
-        for (const plugin of plugins) {
-          for (const [id, def] of Object.entries(plugin.tool ?? {})) {
-            custom.push(fromPlugin(id, def))
+          const plugins = await Plugin.list()
+          for (const plugin of plugins) {
+            for (const [id, def] of Object.entries(plugin.tool ?? {})) {
+              custom.push(fromPlugin(id, def))
+            }
           }
-        }
+        })
       })
 
+      const loadFiber = yield* load().pipe(
+        Effect.catchCause(() => Effect.void),
+        Effect.forkScoped,
+      )
+
       function fromPlugin(id: string, def: ToolDefinition): Tool.Info {
         return {
           id,
@@ -131,6 +138,7 @@ export namespace ToolRegistry {
       }
 
       const register = Effect.fn("ToolRegistry.register")(function* (tool: Tool.Info) {
+        yield* Fiber.join(loadFiber)
         const idx = custom.findIndex((t) => t.id === tool.id)
         if (idx >= 0) {
           custom.splice(idx, 1, tool)
@@ -140,6 +148,7 @@ export namespace ToolRegistry {
       })
 
       const ids = Effect.fn("ToolRegistry.ids")(function* () {
+        yield* Fiber.join(loadFiber)
         const tools = yield* Effect.promise(() => all())
         return tools.map((t) => t.id)
       })
@@ -148,6 +157,7 @@ export namespace ToolRegistry {
         model: { providerID: ProviderID; modelID: ModelID },
         agent?: Agent.Info,
       ) {
+        yield* Fiber.join(loadFiber)
         const allTools = yield* Effect.promise(() => all())
         return yield* Effect.promise(() =>
           Promise.all(