Explorar el Código

refactor(mcp): simplify service helpers (#31549)

Aiden Cline hace 3 meses
padre
commit
381eabb970
Se han modificado 1 ficheros con 28 adiciones y 48 borrados
  1. 28 48
      packages/opencode/src/mcp/index.ts

+ 28 - 48
packages/opencode/src/mcp/index.ts

@@ -115,7 +115,7 @@ function isMcpConfigured(entry: McpEntry): entry is ConfigMCPV1.Info {
 const sanitize = (s: string) => s.replace(/[^a-zA-Z0-9_-]/g, "_")
 const sanitize = (s: string) => s.replace(/[^a-zA-Z0-9_-]/g, "_")
 const MAX_LIST_PAGES = 1_000
 const MAX_LIST_PAGES = 1_000
 
 
-function remoteURL(key: string, value: string) {
+function remoteURL(value: string) {
   if (URL.canParse(value)) return new URL(value)
   if (URL.canParse(value)) return new URL(value)
 }
 }
 
 
@@ -197,11 +197,7 @@ function convertMcpTool(mcpTool: MCPToolDef, client: MCPClient, timeout?: number
 }
 }
 
 
 function defs(client: MCPClient, timeout?: number) {
 function defs(client: MCPClient, timeout?: number) {
-  return listTools(client, timeout ?? DEFAULT_TIMEOUT).pipe(
-    Effect.catch((err) => {
-      return Effect.succeed(undefined)
-    }),
-  )
+  return listTools(client, timeout ?? DEFAULT_TIMEOUT).pipe(Effect.catch(() => Effect.void))
 }
 }
 
 
 function fetchFromClient<T extends { name: string }>(
 function fetchFromClient<T extends { name: string }>(
@@ -212,9 +208,7 @@ function fetchFromClient<T extends { name: string }>(
 ) {
 ) {
   return Effect.tryPromise({
   return Effect.tryPromise({
     try: () => listFn(client),
     try: () => listFn(client),
-    catch: (e: any) => {
-      return e
-    },
+    catch: (error) => error,
   }).pipe(
   }).pipe(
     Effect.tapError((error) =>
     Effect.tapError((error) =>
       Effect.logWarning(`failed to get ${label}`, {
       Effect.logWarning(`failed to get ${label}`, {
@@ -323,7 +317,7 @@ export const layer = Layer.effect(
     ) {
     ) {
       const oauthDisabled = mcp.oauth === false
       const oauthDisabled = mcp.oauth === false
       const oauthConfig = typeof mcp.oauth === "object" ? mcp.oauth : undefined
       const oauthConfig = typeof mcp.oauth === "object" ? mcp.oauth : undefined
-      const url = remoteURL(key, mcp.url)
+      const url = remoteURL(mcp.url)
       if (!url) {
       if (!url) {
         return {
         return {
           client: undefined as MCPClient | undefined,
           client: undefined as MCPClient | undefined,
@@ -407,12 +401,10 @@ export const layer = Layer.effect(
             }
             }
 
 
             lastStatus = { status: "failed" as const, error: lastError.message }
             lastStatus = { status: "failed" as const, error: lastError.message }
-            return Effect.succeed(undefined)
+            return Effect.void
           }),
           }),
         )
         )
-        if (result) {
-          return { client: result.client as MCPClient | undefined, status: { status: "connected" } as Status }
-        }
+        if (result) return { client: result.client, status: { status: "connected" } as Status }
         // If this was an auth error, stop trying other transports
         // If this was an auth error, stop trying other transports
         if (lastStatus?.status === "needs_auth" || lastStatus?.status === "needs_client_registration") break
         if (lastStatus?.status === "needs_auth" || lastStatus?.status === "needs_client_registration") break
       }
       }
@@ -486,8 +478,8 @@ export const layer = Layer.effect(
         if (process.platform === "win32") return [] as number[]
         if (process.platform === "win32") return [] as number[]
         const pids: number[] = []
         const pids: number[] = []
         const queue = [pid]
         const queue = [pid]
-        while (queue.length > 0) {
-          const current = queue.shift()!
+        for (let index = 0; index < queue.length; index++) {
+          const current = queue[index]
           const handle = yield* spawner.spawn(ChildProcess.make("pgrep", ["-P", String(current)], { stdin: "ignore" }))
           const handle = yield* spawner.spawn(ChildProcess.make("pgrep", ["-P", String(current)], { stdin: "ignore" }))
           const text = yield* Stream.mkString(Stream.decodeText(handle.stdout))
           const text = yield* Stream.mkString(Stream.decodeText(handle.stdout))
           yield* handle.exitCode
           yield* handle.exitCode
@@ -674,30 +666,20 @@ export const layer = Layer.effect(
       const config = cfg.mcp ?? {}
       const config = cfg.mcp ?? {}
       const defaultTimeout = cfg.experimental?.mcp_timeout
       const defaultTimeout = cfg.experimental?.mcp_timeout
 
 
-      const connectedClients = Object.entries(s.clients).filter(
-        ([clientName]) => s.status[clientName]?.status === "connected",
-      )
-
-      yield* Effect.forEach(
-        connectedClients,
-        ([clientName, client]) =>
-          Effect.gen(function* () {
-            const mcpConfig = config[clientName]
-            const entry = mcpConfig && isMcpConfigured(mcpConfig) ? mcpConfig : s.config[clientName]
-
-            const listed = s.defs[clientName]
-            if (!listed) {
-              yield* Effect.logWarning("missing cached tools for connected server", { clientName })
-              return
-            }
-
-            const timeout = entry?.timeout ?? defaultTimeout
-            for (const mcpTool of listed) {
-              result[sanitize(clientName) + "_" + sanitize(mcpTool.name)] = convertMcpTool(mcpTool, client, timeout)
-            }
-          }),
-        { concurrency: "unbounded" },
-      )
+      for (const [clientName, client] of Object.entries(s.clients)) {
+        if (s.status[clientName]?.status !== "connected") continue
+        const mcpConfig = config[clientName]
+        const entry = mcpConfig && isMcpConfigured(mcpConfig) ? mcpConfig : s.config[clientName]
+        const listed = s.defs[clientName]
+        if (!listed) {
+          yield* Effect.logWarning("missing cached tools for connected server", { clientName })
+          continue
+        }
+        const timeout = entry?.timeout ?? defaultTimeout
+        for (const mcpTool of listed) {
+          result[sanitize(clientName) + "_" + sanitize(mcpTool.name)] = convertMcpTool(mcpTool, client, timeout)
+        }
+      }
       return result
       return result
     })
     })
 
 
@@ -758,9 +740,7 @@ export const layer = Layer.effect(
       }
       }
       return yield* Effect.tryPromise({
       return yield* Effect.tryPromise({
         try: () => fn(client),
         try: () => fn(client),
-        catch: (e: any) => {
-          return e
-        },
+        catch: (error) => error,
       }).pipe(
       }).pipe(
         Effect.tapError((error) =>
         Effect.tapError((error) =>
           Effect.logError(`failed to ${label}`, {
           Effect.logError(`failed to ${label}`, {
@@ -809,7 +789,7 @@ export const layer = Layer.effect(
       const mcpConfig = yield* requireMcpConfig(mcpName)
       const mcpConfig = yield* requireMcpConfig(mcpName)
       if (mcpConfig.type !== "remote") throw new Error(`MCP server ${mcpName} is not a remote server`)
       if (mcpConfig.type !== "remote") throw new Error(`MCP server ${mcpName} is not a remote server`)
       if (mcpConfig.oauth === false) throw new Error(`MCP server ${mcpName} has OAuth explicitly disabled`)
       if (mcpConfig.oauth === false) throw new Error(`MCP server ${mcpName} has OAuth explicitly disabled`)
-      const url = remoteURL(mcpName, mcpConfig.url)
+      const url = remoteURL(mcpConfig.url)
       if (!url) throw new Error(`Invalid MCP URL for "${mcpName}"`)
       if (!url) throw new Error(`Invalid MCP URL for "${mcpName}"`)
 
 
       // OAuth config is optional - if not provided, we'll use auto-discovery
       // OAuth config is optional - if not provided, we'll use auto-discovery
@@ -881,7 +861,7 @@ export const layer = Layer.effect(
           : undefined
           : undefined
         if (!client || !listed) {
         if (!client || !listed) {
           yield* Effect.tryPromise(() => client?.close() ?? Promise.resolve()).pipe(Effect.ignore)
           yield* Effect.tryPromise(() => client?.close() ?? Promise.resolve()).pipe(Effect.ignore)
-          return { status: "failed", error: "Failed to get tools" } as Status
+          return { status: "failed", error: "Failed to get tools" } satisfies Status
         }
         }
 
 
         const s = yield* InstanceState.get(state)
         const s = yield* InstanceState.get(state)
@@ -936,7 +916,7 @@ export const layer = Layer.effect(
       }).pipe(Effect.option)
       }).pipe(Effect.option)
 
 
       if (Option.isNone(result)) {
       if (Option.isNone(result)) {
-        return { status: "failed", error: "OAuth completion failed" } as Status
+        return { status: "failed", error: "OAuth completion failed" } satisfies Status
       }
       }
 
 
       yield* auth.clearCodeVerifier(mcpName)
       yield* auth.clearCodeVerifier(mcpName)
@@ -965,9 +945,9 @@ export const layer = Layer.effect(
 
 
     const getAuthStatus = Effect.fn("MCP.getAuthStatus")(function* (mcpName: string) {
     const getAuthStatus = Effect.fn("MCP.getAuthStatus")(function* (mcpName: string) {
       const entry = yield* auth.get(mcpName)
       const entry = yield* auth.get(mcpName)
-      if (!entry?.tokens) return "not_authenticated" as AuthStatus
+      if (!entry?.tokens) return "not_authenticated"
       const expired = yield* auth.isTokenExpired(mcpName)
       const expired = yield* auth.isTokenExpired(mcpName)
-      return (expired ? "expired" : "authenticated") as AuthStatus
+      return expired ? "expired" : "authenticated"
     })
     })
 
 
     return Service.of({
     return Service.of({