@@ -46,7 +46,12 @@ import {
4646} from "@/common/utils/tools/toolDefinitions" ;
4747import type { MuxMessage } from "@/common/types/message" ;
4848import type { RuntimeConfig } from "@/common/types/runtime" ;
49- import { hasSrcBaseDir , getSrcBaseDir , isSSHRuntime } from "@/common/types/runtime" ;
49+ import {
50+ hasSrcBaseDir ,
51+ getSrcBaseDir ,
52+ isSSHRuntime ,
53+ isDockerRuntime ,
54+ } from "@/common/types/runtime" ;
5055import { defaultModel , isValidModelFormat , normalizeGatewayModel } from "@/common/utils/ai/models" ;
5156import type { StreamEndEvent , StreamAbortEvent } from "@/common/types/stream" ;
5257import type { TerminalService } from "@/node/services/terminalService" ;
@@ -1573,17 +1578,19 @@ export class WorkspaceService extends EventEmitter {
15731578 const planPath = getPlanFilePath ( metadata . name , metadata . projectName ) ;
15741579 const legacyPlanPath = getLegacyPlanFilePath ( workspaceId ) ;
15751580
1576- // For SSH: use $HOME expansion so remote shell resolves to remote home directory
1577- // For local: expand tilde locally since shellQuote prevents shell expansion
1578- const quotedPlanPath = isSSHRuntime ( metadata . runtimeConfig )
1581+ const isRemoteRuntime =
1582+ isSSHRuntime ( metadata . runtimeConfig ) || isDockerRuntime ( metadata . runtimeConfig ) ;
1583+
1584+ // For SSH/Docker: use $HOME expansion so the runtime shell resolves to the runtime home directory.
1585+ // For local: expand tilde locally since shellQuote prevents shell expansion.
1586+ const quotedPlanPath = isRemoteRuntime
15791587 ? expandTildeForSSH ( planPath )
15801588 : shellQuote ( expandTilde ( planPath ) ) ;
1581- const quotedLegacyPlanPath = isSSHRuntime ( metadata . runtimeConfig )
1589+ const quotedLegacyPlanPath = isRemoteRuntime
15821590 ? expandTildeForSSH ( legacyPlanPath )
15831591 : shellQuote ( expandTilde ( legacyPlanPath ) ) ;
15841592
1585- // SSH runtime: delete via remote shell so $HOME expands on the remote.
1586- if ( isSSHRuntime ( metadata . runtimeConfig ) ) {
1593+ if ( isRemoteRuntime ) {
15871594 const runtime = createRuntime ( metadata . runtimeConfig , {
15881595 projectPath : metadata . projectPath ,
15891596 } ) ;
@@ -1595,8 +1602,16 @@ export class WorkspaceService extends EventEmitter {
15951602 cwd : metadata . projectPath ,
15961603 timeout : 10 ,
15971604 } ) ;
1598- // Wait for completion so callers can rely on the plan file actually being removed.
1599- await execStream . exitCode ;
1605+
1606+ try {
1607+ await execStream . stdin . close ( ) ;
1608+ } catch {
1609+ // Ignore stdin-close errors (e.g. already closed).
1610+ }
1611+
1612+ await execStream . exitCode . catch ( ( ) => {
1613+ // Best-effort: ignore failures.
1614+ } ) ;
16001615 } catch {
16011616 // Plan files don't exist or can't be deleted - ignore
16021617 }
0 commit comments