From d4bf70be06f5e893cc3b9f39b2c68f8df7481508 Mon Sep 17 00:00:00 2001 From: Luke Parker <10430890+Hona@users.noreply.github.com> Date: Wed, 29 Apr 2026 09:10:48 +1000 Subject: [PATCH] fix(bash): memory leak - release parsed syntax trees (#24861) Co-authored-by: jiwenshang --- packages/opencode/src/tool/bash.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts index 8593899497..517512ff4c 100644 --- a/packages/opencode/src/tool/bash.ts +++ b/packages/opencode/src/tool/bash.ts @@ -252,7 +252,7 @@ function tail(text: string, maxLines: number, maxBytes: number) { const parse = Effect.fn("BashTool.parse")(function* (command: string, ps: boolean) { const tree = yield* Effect.promise(() => parser().then((p) => (ps ? p.ps : p.bash).parse(command))) if (!tree) throw new Error("Failed to parse command") - return tree.rootNode + return tree }) const ask = Effect.fn("BashTool.ask")(function* (ctx: Tool.Context, scan: Scan) { @@ -596,10 +596,17 @@ export const BashTool = Tool.define( } const timeout = params.timeout ?? DEFAULT_TIMEOUT const ps = Shell.ps(shell) - const root = yield* parse(params.command, ps) - const scan = yield* collect(root, cwd, ps, shell) - if (!Instance.containsPath(cwd)) scan.dirs.add(cwd) - yield* ask(ctx, scan) + yield* Effect.scoped( + Effect.gen(function* () { + const tree = yield* Effect.acquireRelease( + parse(params.command, ps), + (tree) => Effect.sync(() => tree.delete()), + ) + const scan = yield* collect(tree.rootNode, cwd, ps, shell) + if (!Instance.containsPath(cwd)) scan.dirs.add(cwd) + yield* ask(ctx, scan) + }), + ) return yield* run( {