From a538eb3d2789034acac27a499d89fdeb9e423e98 Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Fri, 22 May 2026 07:55:28 +0200 Subject: [PATCH 1/2] fix(shell): add timeout guards for pre-spawn pipeline and post-SIGKILL cleanup --- packages/core/src/cross-spawn-spawner.ts | 12 ++++++++++-- packages/opencode/src/tool/shell.ts | 5 +++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/core/src/cross-spawn-spawner.ts b/packages/core/src/cross-spawn-spawner.ts index ad8d4126d454..3bfc4664a4e5 100644 --- a/packages/core/src/cross-spawn-spawner.ts +++ b/packages/core/src/cross-spawn-spawner.ts @@ -393,7 +393,11 @@ export const make = Effect.gen(function* () { const escalated = command.options.forceKillAfter ? Effect.timeoutOrElse(attempt, { duration: command.options.forceKillAfter, - orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid), + orElse: () => + send("SIGKILL").pipe( + Effect.andThen(Deferred.await(signal).pipe(Effect.timeout("5 seconds"), Effect.ignore)), + Effect.asVoid, + ), }) : attempt return yield* Effect.ignore(escalated) @@ -430,7 +434,11 @@ export const make = Effect.gen(function* () { if (!opts?.forceKillAfter) return attempt return Effect.timeoutOrElse(attempt, { duration: opts.forceKillAfter, - orElse: () => send("SIGKILL").pipe(Effect.andThen(Deferred.await(signal)), Effect.asVoid), + orElse: () => + send("SIGKILL").pipe( + Effect.andThen(Deferred.await(signal).pipe(Effect.timeout("5 seconds"), Effect.ignore)), + Effect.asVoid, + ), }) }, unref: Effect.sync(() => { diff --git a/packages/opencode/src/tool/shell.ts b/packages/opencode/src/tool/shell.ts index 506d98466e76..be8c61390d4d 100644 --- a/packages/opencode/src/tool/shell.ts +++ b/packages/opencode/src/tool/shell.ts @@ -627,6 +627,11 @@ export const ShellTool = Tool.define( if (!containsPath(cwd, instanceCtx)) scan.dirs.add(cwd) yield* ask(ctx, scan) }), + ).pipe( + Effect.timeoutOrElse({ + duration: "10 seconds", + orElse: () => Effect.void, + }), ) return yield* run( From 9b0b8554e66546dce2a6752530549c5086e816ce Mon Sep 17 00:00:00 2001 From: Sergey Tihon Date: Fri, 22 May 2026 08:26:10 +0200 Subject: [PATCH 2/2] fix: Copilot review comment --- packages/opencode/src/tool/shell.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/tool/shell.ts b/packages/opencode/src/tool/shell.ts index be8c61390d4d..4eadba2ebcde 100644 --- a/packages/opencode/src/tool/shell.ts +++ b/packages/opencode/src/tool/shell.ts @@ -630,7 +630,12 @@ export const ShellTool = Tool.define( ).pipe( Effect.timeoutOrElse({ duration: "10 seconds", - orElse: () => Effect.void, + orElse: () => + Effect.gen(function* () { + yield* Effect.logWarning( + "Shell command scan/ask phase timed out after 10 seconds; continuing execution without completing that work, so results may be incomplete.", + ) + }), }), )