fix(opencode): clear closed MCP clients (#32084)
This commit is contained in:
@@ -398,6 +398,19 @@ export const layer = Layer.effect(
|
|||||||
)
|
)
|
||||||
|
|
||||||
function watch(s: State, name: string, client: MCPClient, bridge: EffectBridge.Shape, timeout?: number) {
|
function watch(s: State, name: string, client: MCPClient, bridge: EffectBridge.Shape, timeout?: number) {
|
||||||
|
client.onclose = () => {
|
||||||
|
if (s.clients[name] !== client) return
|
||||||
|
delete s.clients[name]
|
||||||
|
delete s.defs[name]
|
||||||
|
s.status[name] = { status: "failed", error: "Connection closed" }
|
||||||
|
bridge.fork(
|
||||||
|
Effect.logWarning("MCP connection closed", { server: name }).pipe(
|
||||||
|
Effect.andThen(events.publish(ToolsChanged, { server: name })),
|
||||||
|
Effect.ignore,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) =>
|
client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) =>
|
||||||
bridge.promise(serverLog(name, notification.params)),
|
bridge.promise(serverLog(name, notification.params)),
|
||||||
)
|
)
|
||||||
@@ -472,8 +485,11 @@ export const layer = Layer.effect(
|
|||||||
|
|
||||||
yield* Effect.addFinalizer(() =>
|
yield* Effect.addFinalizer(() =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
|
const clients = Object.values(s.clients)
|
||||||
|
s.clients = {}
|
||||||
|
s.defs = {}
|
||||||
yield* Effect.forEach(
|
yield* Effect.forEach(
|
||||||
Object.values(s.clients),
|
clients,
|
||||||
(client) =>
|
(client) =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const pid = client.transport instanceof StdioClientTransport ? client.transport.pid : null
|
const pid = client.transport instanceof StdioClientTransport ? client.transport.pid : null
|
||||||
@@ -499,6 +515,7 @@ export const layer = Layer.effect(
|
|||||||
|
|
||||||
function closeClient(s: State, name: string) {
|
function closeClient(s: State, name: string) {
|
||||||
const client = s.clients[name]
|
const client = s.clients[name]
|
||||||
|
delete s.clients[name]
|
||||||
delete s.defs[name]
|
delete s.defs[name]
|
||||||
if (!client) return Effect.void
|
if (!client) return Effect.void
|
||||||
return Effect.tryPromise(() => client.close()).pipe(Effect.ignore)
|
return Effect.tryPromise(() => client.close()).pipe(Effect.ignore)
|
||||||
@@ -512,11 +529,12 @@ export const layer = Layer.effect(
|
|||||||
timeout?: number,
|
timeout?: number,
|
||||||
) {
|
) {
|
||||||
const bridge = yield* EffectBridge.make()
|
const bridge = yield* EffectBridge.make()
|
||||||
yield* closeClient(s, name)
|
const previous = s.clients[name]
|
||||||
s.status[name] = { status: "connected" }
|
s.status[name] = { status: "connected" }
|
||||||
s.clients[name] = client
|
s.clients[name] = client
|
||||||
s.defs[name] = listed
|
s.defs[name] = listed
|
||||||
watch(s, name, client, bridge, timeout)
|
watch(s, name, client, bridge, timeout)
|
||||||
|
if (previous) yield* Effect.tryPromise(() => previous.close()).pipe(Effect.ignore)
|
||||||
return s.status[name]
|
return s.status[name]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user