|
1 | 1 | import type { Runtime, BackgroundHandle } from "@/node/runtime/Runtime"; |
2 | 2 | import { spawnProcess } from "./backgroundProcessExecutor"; |
| 3 | +import assert from "@/common/utils/assert"; |
3 | 4 | import { getErrorMessage } from "@/common/utils/errors"; |
4 | 5 | import { log } from "./log"; |
5 | 6 | import { AsyncMutex } from "@/node/utils/concurrency/asyncMutex"; |
@@ -144,6 +145,30 @@ export class BackgroundProcessManager extends EventEmitter<BackgroundProcessMana |
144 | 145 | return this.bgOutputDir; |
145 | 146 | } |
146 | 147 |
|
| 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 | + |
147 | 172 | /** |
148 | 173 | * Spawn a new process with background-style infrastructure. |
149 | 174 | * |
@@ -175,13 +200,7 @@ export class BackgroundProcessManager extends EventEmitter<BackgroundProcessMana |
175 | 200 | > { |
176 | 201 | log.debug(`BackgroundProcessManager.spawn() called for workspace ${workspaceId}`); |
177 | 202 |
|
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); |
185 | 204 |
|
186 | 205 | // Spawn via executor with background infrastructure |
187 | 206 | // spawnProcess uses runtime.tempDir() internally for output directory |
|
0 commit comments