fix(plugin): reuse active server for client requests

Temporarily route plugin SDK calls through the active listener so they reuse its instance store instead of initializing plugins again through the default app. Keep the in-process fallback for commands without a listener. This is intentionally a narrow bridge until v2 owns plugin clients in the correct shared server runtime.
This commit is contained in:
Dax Raad
2026-06-14 13:35:05 -04:00
parent 3f81402663
commit 87c33b3d85
3 changed files with 70 additions and 8 deletions
+3 -2
View File
@@ -138,11 +138,12 @@ export const layer = Layer.effect(
const { Server } = yield* Effect.promise(() => import("../server/server"))
const serverUrl = Server.url
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
baseUrl: serverUrl?.toString() ?? "http://localhost:4096",
directory: ctx.directory,
headers: ServerAuth.headers(),
fetch: async (...args) => Server.Default().app.fetch(...args),
...(serverUrl ? {} : { fetch: async (...args) => Server.Default().app.fetch(...args) }),
})
const cfg = yield* config.get()
const input: PluginInput = {
+14 -6
View File
@@ -67,7 +67,7 @@ export async function openapi() {
return OpenApi.fromApi(PublicApi)
}
export let url: URL
export let url: URL | undefined
export async function listen(opts: ListenOptions): Promise<Listener> {
const listener = await Effect.runPromise(listenEffect(opts))
@@ -84,15 +84,14 @@ const listenEffect: (opts: ListenOptions) => Effect.Effect<EffectListener, unkno
const state = yield* startWithPortFallback(opts)
const address = yield* tcpAddress(state)
const listenerUrl = makeURL(opts.hostname, address.port)
url = listenerUrl
const unpublishMdns = yield* setupMdns(opts, address.port, state.scope)
url = listenerUrl
return {
hostname: opts.hostname,
port: address.port,
url: listenerUrl,
stop: yield* makeStop(state, unpublishMdns),
stop: yield* makeStop(state, unpublishMdns, listenerUrl),
}
},
)
@@ -169,10 +168,19 @@ function setupMdns(opts: ListenOptions, port: number, scope: Scope.Scope) {
})
}
function makeStop(state: ListenerState, unpublishMdns: Effect.Effect<void>) {
function makeStop(state: ListenerState, unpublishMdns: Effect.Effect<void>, listenerUrl: URL) {
return Effect.gen(function* () {
const forceCloseOnce = yield* Effect.cached(forceClose(state).pipe(Effect.ignore))
const closeScopeOnce = yield* Effect.cached(Scope.close(state.scope, Exit.void).pipe(Effect.ignore))
const closeScopeOnce = yield* Effect.cached(
Scope.close(state.scope, Exit.void).pipe(
Effect.ignore,
Effect.ensuring(
Effect.sync(() => {
if (url === listenerUrl) url = undefined
}),
),
),
)
return (close?: boolean) =>
Effect.gen(function* () {