()
| 223 | }; |
| 224 | |
| 225 | const moveToBackground = () => { |
| 226 | if (isResolved) return; |
| 227 | isResolved = true; |
| 228 | |
| 229 | if (timeoutId) { |
| 230 | clearTimeout(timeoutId); |
| 231 | } |
| 232 | backgroundSignalManager.off("backgroundRequested", moveToBackground); |
| 233 | |
| 234 | // Detach stdout/stderr listeners so they don't accumulate in local |
| 235 | // buffers or trigger chat history updates after the tool call resolves. |
| 236 | // BackgroundJobService.createJobWithProcess attaches its own listeners. |
| 237 | child.stdout.removeListener("data", onStdout); |
| 238 | child.stderr.removeListener("data", onStderr); |
| 239 | |
| 240 | const job = backgroundJobService.createJobWithProcess( |
| 241 | command, |
| 242 | child as ChildProcess, |
| 243 | stdout, |
| 244 | ); |
| 245 | |
| 246 | if (job) { |
| 247 | const truncationResult = truncateOutputFromStart(stdout, { |
| 248 | maxChars, |
| 249 | maxLines, |
| 250 | }); |
| 251 | const outputSoFar = truncationResult.wasTruncated |
| 252 | ? appendParallelLimitNote(truncationResult.output) |
| 253 | : truncationResult.output; |
| 254 | resolve( |
| 255 | `Command moved to background. Job ID: ${job.id}\nOutput so far:\n${outputSoFar}\nUse CheckBackgroundJob("${job.id}") to check status.`, |
| 256 | ); |
| 257 | } else { |
| 258 | resolve( |
| 259 | `Failed to move to background (job limit reached). Command continues in foreground.\nOutput so far: ${stdout}`, |
| 260 | ); |
| 261 | } |
| 262 | }; |
| 263 | |
| 264 | backgroundSignalManager.on("backgroundRequested", moveToBackground); |
| 265 |
nothing calls this directly
no test coverage detected