import { Readable, Writable } from 'node:stream'; import type { ChildProcess } from 'node:child_process'; import { ndJsonStream } from '@agentclientprotocol/sdk'; export function nodeReadableToWeb(nodeStream: NodeJS.ReadableStream): ReadableStream { return new ReadableStream({ start(controller) { nodeStream.on('data', (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk))); nodeStream.on('end', () => controller.close()); nodeStream.on('error', (err) => controller.error(err)); }, cancel() { if ('destroy' in nodeStream && typeof (nodeStream as Readable).destroy === 'function') { (nodeStream as Readable).destroy(); } }, }); } export function nodeWritableToWeb(nodeStream: NodeJS.WritableStream): WritableStream { return new WritableStream({ write(chunk) { return new Promise((resolve, reject) => { const ok = (nodeStream as Writable).write(chunk, (err) => { if (err) reject(err); }); if (ok) resolve(); else (nodeStream as Writable).once('drain', resolve); }); }, close() { return new Promise((resolve) => { (nodeStream as Writable).end(resolve); }); }, abort() { (nodeStream as Writable).destroy(); }, }); } export function createAcpNdJsonStream(child: ChildProcess) { return ndJsonStream(nodeWritableToWeb(child.stdin!), nodeReadableToWeb(child.stdout!)); }