4ea7562f50
Introduces: - src/shared/process-stream-reader.ts: Buffer-concat stream reader compatible with both Bun and Node ChildProcess stdout (replaces Web Response API usage) - src/tools/shared/search-process-output.ts: structured subprocess output collector with timeout, kill, and rejection cleanup - bun-spawn-shim hardened: Node path forces windowsHide: true; spawn errors no longer escape as unhandledRejection Foundation for #3919 fix. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
import type { SpawnedProcess } from "../../shared/bun-spawn-shim"
|
|
import { readProcessStream } from "../../shared/process-stream-reader"
|
|
|
|
export interface SearchProcessOutput {
|
|
readonly stdout: string
|
|
readonly stderr: string
|
|
readonly exitCode: number
|
|
}
|
|
|
|
function getErrorMessage(error: unknown): string {
|
|
return error instanceof Error ? error.message : String(error)
|
|
}
|
|
|
|
function createProcessTimeout(
|
|
proc: SpawnedProcess,
|
|
timeoutMs: number,
|
|
timeoutMessage: string
|
|
): Promise<never> {
|
|
return new Promise<never>((_, reject) => {
|
|
const id = setTimeout(() => {
|
|
proc.kill()
|
|
reject(new Error(timeoutMessage))
|
|
}, timeoutMs)
|
|
|
|
// #3919: Handle rejected exits here so timeout cleanup cannot leak unhandled rejections.
|
|
void proc.exited.then(
|
|
() => clearTimeout(id),
|
|
() => clearTimeout(id)
|
|
)
|
|
})
|
|
}
|
|
|
|
export async function collectSearchProcessOutput(
|
|
proc: SpawnedProcess,
|
|
timeoutMs: number,
|
|
timeoutMessage: string
|
|
): Promise<SearchProcessOutput> {
|
|
const stderrPromise = readProcessStream(proc.stderr).catch(getErrorMessage)
|
|
const stdout = await Promise.race([
|
|
readProcessStream(proc.stdout),
|
|
createProcessTimeout(proc, timeoutMs, timeoutMessage),
|
|
])
|
|
const [exitCode, stderr] = await Promise.all([proc.exited, stderrPromise])
|
|
|
|
return { stdout, stderr, exitCode }
|
|
}
|