Skip to content

Commit b409aae

Browse files
committed
🤖 fix: wait for plan file deletion
deletePlanFilesForWorkspace() used runtime.exec() without waiting for completion. Await stdin.close() + exitCode so callers can assume plan files are gone when it resolves. --- _Generated with `mux` • Model: `openai:gpt-5.2` • Thinking: `xhigh`_
1 parent a897bd8 commit b409aae

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

src/node/services/workspaceService.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ import {
4646
} from "@/common/utils/tools/toolDefinitions";
4747
import type { MuxMessage } from "@/common/types/message";
4848
import 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";
5055
import { defaultModel, isValidModelFormat, normalizeGatewayModel } from "@/common/utils/ai/models";
5156
import type { StreamEndEvent, StreamAbortEvent } from "@/common/types/stream";
5257
import 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

Comments
 (0)