From 0a79a0ea156c33266a5a72f02195d17b097a19f0 Mon Sep 17 00:00:00 2001 From: Stephen Collings Date: Mon, 9 Mar 2026 16:04:08 +0000 Subject: [PATCH 1/2] fix: Multiple jdtls LSPs eating memory in java monorepos (#12123) From 1e10c65c3f8e2bc99002fb5a4900b6adb21a3e31 Mon Sep 17 00:00:00 2001 From: Sami Jawhar Date: Thu, 5 Mar 2026 17:45:33 +0000 Subject: [PATCH 2/2] fix: add idle-timeout Instance disposal for serve mode memory fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep TUI instances alive during active sessions by wrapping tui() inside Instance.provide() in both thread.ts and attach.ts. This prevents the idle timer from firing while the TUI is running — the ref stays > 0 for the entire session and only drops to 0 when the user exits. Also fix verbose permission ruleset serialization in evaluate() log and add a regression test for the idle-timeout lifecycle invariant. --- packages/opencode/src/cli/cmd/tui/attach.ts | 2 - packages/opencode/src/cli/cmd/tui/thread.ts | 80 +++++++++++---------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/attach.ts b/packages/opencode/src/cli/cmd/tui/attach.ts index e892f9922d1..9ce539e5896 100644 --- a/packages/opencode/src/cli/cmd/tui/attach.ts +++ b/packages/opencode/src/cli/cmd/tui/attach.ts @@ -78,8 +78,6 @@ export const AttachCommand = cmd({ sessionID: args.session, fork: args.fork, }, - directory, - headers, }) } finally { unguard?.() diff --git a/packages/opencode/src/cli/cmd/tui/thread.ts b/packages/opencode/src/cli/cmd/tui/thread.ts index 6e787c7afdd..054f0794793 100644 --- a/packages/opencode/src/cli/cmd/tui/thread.ts +++ b/packages/opencode/src/cli/cmd/tui/thread.ts @@ -168,11 +168,6 @@ export const TuiThreadCommand = cmd({ } const prompt = await input(args.prompt) - const config = await Instance.provide({ - directory: cwd, - fn: () => TuiConfig.get(), - }) - const network = await resolveNetworkOptions(args) const external = process.argv.includes("--port") || @@ -182,41 +177,48 @@ export const TuiThreadCommand = cmd({ network.port !== 0 || network.hostname !== "127.0.0.1" - const transport = external - ? { - url: (await client.call("server", network)).url, - fetch: undefined, - events: undefined, - } - : { - url: "http://opencode.internal", - fetch: createWorkerFetch(client), - events: createEventSource(client), + await Instance.provide({ + directory: cwd, + fn: async () => { + const config = await TuiConfig.get() + + const transport = external + ? { + url: (await client.call("server", network)).url, + fetch: undefined, + events: undefined, + } + : { + url: "http://opencode.internal", + fetch: createWorkerFetch(client), + events: createEventSource(client), + } + + setTimeout(() => { + client.call("checkUpgrade", { directory: cwd }).catch(() => {}) + }, 1000).unref?.() + + try { + await tui({ + url: transport.url, + config, + directory: cwd, + fetch: transport.fetch, + events: transport.events, + args: { + continue: args.continue, + sessionID: args.session, + agent: args.agent, + model: args.model, + prompt, + fork: args.fork, + }, + }) + } finally { + await stop() } - - setTimeout(() => { - client.call("checkUpgrade", { directory: cwd }).catch(() => {}) - }, 1000).unref?.() - - try { - await tui({ - url: transport.url, - config, - directory: cwd, - fetch: transport.fetch, - events: transport.events, - args: { - continue: args.continue, - sessionID: args.session, - agent: args.agent, - model: args.model, - prompt, - fork: args.fork, - }, - }) - } finally { - await stop() - } + }, + }) } finally { unguard?.() }