fix(core): ensure binary shell output files are still written to disk for 20MB files, and wait for stream close

This commit is contained in:
Spencer
2026-04-10 15:47:53 +00:00
parent c2a17ae257
commit 63a6211fe0
2 changed files with 45 additions and 12 deletions

View File

@@ -70,12 +70,27 @@ describe('run_shell_command streaming to file regression', () => {
files.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
for (const p of files) {
const stat = fs.statSync(p);
if (stat.size >= 20000000) {
savedFilePath = p;
break;
try {
const stat = fs.statSync(p);
if (stat.size >= 20000000) {
savedFilePath = p;
break;
}
} catch {
// ignore
}
}
if (!savedFilePath) {
const fileStats = files.map((p) => {
try {
return { p, size: fs.statSync(p).size };
} catch {
return { p, size: 'error' };
}
});
console.error('Available files:', JSON.stringify(fileStats, null, 2));
}
}
expect(
@@ -144,12 +159,27 @@ describe('run_shell_command streaming to file regression', () => {
files.sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
for (const p of files) {
const stat = fs.statSync(p);
if (stat.size >= 20000000) {
savedFilePath = p;
break;
try {
const stat = fs.statSync(p);
if (stat.size >= 20000000) {
savedFilePath = p;
break;
}
} catch {
// ignore
}
}
if (!savedFilePath) {
const fileStats = files.map((p) => {
try {
return { p, size: fs.statSync(p).size };
} catch {
return { p, size: 'error' };
}
});
console.error('Available files:', JSON.stringify(fileStats, null, 2));
}
}
expect(

View File

@@ -532,10 +532,8 @@ export class ShellToolInvocation extends BaseToolInvocation<
// We rely on 'file_data' for the clean output stream.
break;
case 'file_data':
if (!isBinaryStream) {
totalBytesWritten += Buffer.byteLength(event.chunk);
outputStream.write(event.chunk);
}
totalBytesWritten += Buffer.byteLength(event.chunk);
outputStream.write(event.chunk);
break;
case 'data':
if (isBinaryStream) break;
@@ -676,6 +674,11 @@ export class ShellToolInvocation extends BaseToolInvocation<
outputStream.end(resolve);
});
// Ensure the stream is fully closed before we proceed
if (!outputStream.closed) {
await new Promise<void>((resolve) => outputStream.on('close', resolve));
}
const backgroundPIDs: number[] = [];
if (os.platform() !== 'win32') {
let tempFileExists = false;