test(mcp): replace module mocks with real servers (#35450)
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import open from "open"
|
||||
|
||||
export interface Interface {
|
||||
readonly open: (url: string) => Effect.Effect<void, Error>
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/McpBrowser") {}
|
||||
|
||||
const layer = Layer.succeed(
|
||||
Service,
|
||||
Service.of({
|
||||
open: Effect.fn("McpBrowser.open")(function* (url: string) {
|
||||
const subprocess = yield* Effect.tryPromise({
|
||||
try: () => open(url),
|
||||
catch: (error) => (error instanceof Error ? error : new Error(String(error))),
|
||||
})
|
||||
yield* Effect.callback<void, Error>((resume) => {
|
||||
const timer = setTimeout(() => resume(Effect.void), 500)
|
||||
subprocess.on("error", (error) => {
|
||||
clearTimeout(timer)
|
||||
resume(Effect.fail(error))
|
||||
})
|
||||
subprocess.on("exit", (code) => {
|
||||
if (code === null || code === 0) return
|
||||
clearTimeout(timer)
|
||||
resume(Effect.fail(new Error(`Browser open failed with exit code ${code}`)))
|
||||
})
|
||||
})
|
||||
}),
|
||||
}),
|
||||
)
|
||||
|
||||
export const node = LayerNode.make({ service: Service, layer, deps: [] })
|
||||
|
||||
export * as McpBrowser from "./browser"
|
||||
@@ -26,7 +26,6 @@ import { McpOAuthCallback } from "./oauth-callback"
|
||||
import { McpAuth } from "./auth"
|
||||
import { EventV2Bridge } from "@/event-v2-bridge"
|
||||
import { TuiEvent } from "@/server/tui-event"
|
||||
import open from "open"
|
||||
import { Cause, Effect, Exit, Layer, Context, Schema, Stream } from "effect"
|
||||
import { EffectBridge } from "@/effect/bridge"
|
||||
import { InstanceState } from "@/effect/instance-state"
|
||||
@@ -34,6 +33,7 @@ import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process"
|
||||
import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
|
||||
import { McpCatalog } from "./catalog"
|
||||
import { McpEvent } from "@opencode-ai/schema/mcp-event"
|
||||
import { McpBrowser } from "./browser"
|
||||
|
||||
const DEFAULT_TIMEOUT = 30_000
|
||||
const CLIENT_OPTIONS = {
|
||||
@@ -207,6 +207,7 @@ const layer = Layer.effect(
|
||||
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
|
||||
const auth = yield* McpAuth.Service
|
||||
const events = yield* EventV2Bridge.Service
|
||||
const browser = yield* McpBrowser.Service
|
||||
|
||||
type Transport = StdioClientTransport | StreamableHTTPClientTransport | SSEClientTransport
|
||||
|
||||
@@ -897,22 +898,7 @@ const layer = Layer.effect(
|
||||
const callbackPromise = McpOAuthCallback.waitForCallback(result.oauthState, mcpName)
|
||||
onAuthorization?.(result.authorizationUrl)
|
||||
|
||||
yield* Effect.tryPromise(() => open(result.authorizationUrl)).pipe(
|
||||
Effect.flatMap((subprocess) =>
|
||||
Effect.callback<void, Error>((resume) => {
|
||||
const timer = setTimeout(() => resume(Effect.void), 500)
|
||||
subprocess.on("error", (err) => {
|
||||
clearTimeout(timer)
|
||||
resume(Effect.fail(err))
|
||||
})
|
||||
subprocess.on("exit", (code) => {
|
||||
if (code !== null && code !== 0) {
|
||||
clearTimeout(timer)
|
||||
resume(Effect.fail(new Error(`Browser open failed with exit code ${code}`)))
|
||||
}
|
||||
})
|
||||
}),
|
||||
),
|
||||
yield* browser.open(result.authorizationUrl).pipe(
|
||||
Effect.catch(() => {
|
||||
return events.publish(BrowserOpenFailed, { mcpName, url: result.authorizationUrl }).pipe(Effect.ignore)
|
||||
}),
|
||||
@@ -1012,7 +998,7 @@ export type AuthStatus = "authenticated" | "expired" | "not_authenticated"
|
||||
export const node = LayerNode.make({
|
||||
service: Service,
|
||||
layer: layer,
|
||||
deps: [CrossSpawnSpawner.node, McpAuth.node, EventV2Bridge.node, Config.node],
|
||||
deps: [CrossSpawnSpawner.node, McpAuth.node, EventV2Bridge.node, Config.node, McpBrowser.node],
|
||||
})
|
||||
|
||||
export * as MCP from "."
|
||||
|
||||
Reference in New Issue
Block a user