Skip to content

Commit 4a2ea12

Browse files
committed
🤖 fix: dedupe migrated background bash IDs
Change-Id: I4fe6af0fe450b12528335bbb04310dbe37d866cf Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent a76ff50 commit 4a2ea12

File tree

2 files changed

+30
-9
lines changed

2 files changed

+30
-9
lines changed

src/node/services/backgroundProcessManager.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Runtime, BackgroundHandle } from "@/node/runtime/Runtime";
22
import { spawnProcess } from "./backgroundProcessExecutor";
3+
import assert from "@/common/utils/assert";
34
import { getErrorMessage } from "@/common/utils/errors";
45
import { log } from "./log";
56
import { AsyncMutex } from "@/node/utils/concurrency/asyncMutex";
@@ -144,6 +145,30 @@ export class BackgroundProcessManager extends EventEmitter<BackgroundProcessMana
144145
return this.bgOutputDir;
145146
}
146147

148+
/**
149+
* Generate a unique background process ID.
150+
*
151+
* Background process IDs are used as tool-visible identifiers (e.g. task_await with bash: IDs),
152+
* so they must be globally unique across all running processes.
153+
*
154+
* If the base ID is already in use, we append " (1)", " (2)", etc.
155+
*/
156+
generateUniqueProcessId(baseId: string): string {
157+
assert(
158+
typeof baseId === "string" && baseId.length > 0,
159+
"BackgroundProcessManager.generateUniqueProcessId requires a non-empty baseId"
160+
);
161+
162+
let processId = baseId;
163+
let suffix = 1;
164+
while (this.processes.has(processId)) {
165+
processId = `${baseId} (${suffix})`;
166+
suffix++;
167+
}
168+
169+
return processId;
170+
}
171+
147172
/**
148173
* Spawn a new process with background-style infrastructure.
149174
*
@@ -175,13 +200,7 @@ export class BackgroundProcessManager extends EventEmitter<BackgroundProcessMana
175200
> {
176201
log.debug(`BackgroundProcessManager.spawn() called for workspace ${workspaceId}`);
177202

178-
// Generate unique processId, appending (1), (2), etc. on collision
179-
let processId = config.displayName;
180-
let suffix = 1;
181-
while (this.processes.has(processId)) {
182-
processId = `${config.displayName} (${suffix})`;
183-
suffix++;
184-
}
203+
const processId = this.generateUniqueProcessId(config.displayName);
185204

186205
// Spawn via executor with background infrastructure
187206
// spawnProcess uses runtime.tempDir() internally for output directory

src/node/services/tools/bash.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,8 @@ ${script}`;
616616

617617
// Migrate to background tracking if manager is available
618618
if (config.backgroundProcessManager && config.workspaceId) {
619-
const processId = safeDisplayName;
619+
const processId =
620+
config.backgroundProcessManager.generateUniqueProcessId(safeDisplayName);
620621

621622
// Create a synthetic ExecStream for the migration streams
622623
// The UI streams are still being consumed, migration streams continue to files
@@ -647,7 +648,8 @@ ${script}`;
647648
processId,
648649
config.workspaceId,
649650
script,
650-
migrateResult.outputDir
651+
migrateResult.outputDir,
652+
safeDisplayName
651653
);
652654

653655
return {

0 commit comments

Comments
 (0)