diff --git a/integration-tests/run_shell_command_file_stream.test.ts b/integration-tests/run_shell_command_file_stream.test.ts index 69a608eb71..66e47d2b5e 100644 --- a/integration-tests/run_shell_command_file_stream.test.ts +++ b/integration-tests/run_shell_command_file_stream.test.ts @@ -48,36 +48,18 @@ describe('run_shell_command streaming to file regression', () => { await rig.run({ args: prompt }); let savedFilePath = ''; - const tmpdir = path.join(rig.homeDir!, '.gemini', 'tmp'); - if (fs.existsSync(tmpdir)) { - const findFiles = (dir: string): string[] => { - let results: string[] = []; - const list = fs.readdirSync(dir, { withFileTypes: true }); - for (const file of list) { - const fullPath = path.join(dir, file.name); - if (file.isDirectory()) { - results = results.concat(findFiles(fullPath)); - } else if (file.isFile() && file.name.endsWith('.txt')) { - results.push(fullPath); - } - } - return results; - }; - - const files = findFiles(tmpdir); - for (const p of files) { - const stat = fs.statSync(p); - if (Date.now() - stat.mtimeMs < 60000 && stat.size >= 20000000) { - savedFilePath = p; - break; - } - } - } + const toolLogs = rig.readToolLogs(); + const shellCall = toolLogs.find( + (log) => log.toolRequest.name === 'run_shell_command', + ); + expect(shellCall).toBeTruthy(); + savedFilePath = shellCall?.toolResponse?.result?.outputFile; expect( savedFilePath, - `Expected to find a saved output file >= 20MB in ${tmpdir}`, + `Expected the tool response to contain an outputFile`, ).toBeTruthy(); + const savedContent = fs.readFileSync(savedFilePath, 'utf8'); expect(savedContent).toContain(startMarker); expect(savedContent).toContain(endMarker); @@ -117,45 +99,18 @@ describe('run_shell_command streaming to file regression', () => { await rig.run({ args: prompt }); let savedFilePath = ''; - const tmpdir = path.join(rig.homeDir!, '.gemini', 'tmp'); - if (fs.existsSync(tmpdir)) { - const findFiles = (dir: string): string[] => { - let results: string[] = []; - const list = fs.readdirSync(dir, { withFileTypes: true }); - for (const file of list) { - const fullPath = path.join(dir, file.name); - if (file.isDirectory()) { - results = results.concat(findFiles(fullPath)); - } else if (file.isFile() && file.name.endsWith('.txt')) { - results.push(fullPath); - } - } - return results; - }; - - const files = findFiles(tmpdir); - const fileStats = files.map((p) => ({ - p, - size: fs.statSync(p).size, - age: Date.now() - fs.statSync(p).mtimeMs, - })); - for (const p of files) { - const stat = fs.statSync(p); - // Look for file >= 20MB (since we expect 50MB, but allowing margin for the bug) - if (Date.now() - stat.mtimeMs < 60000 && stat.size >= 20000000) { - savedFilePath = p; - break; - } - } - if (!savedFilePath) { - console.error('Available files:', JSON.stringify(fileStats, null, 2)); - } - } + const toolLogs = rig.readToolLogs(); + const shellCall = toolLogs.find( + (log) => log.toolRequest.name === 'run_shell_command', + ); + expect(shellCall).toBeTruthy(); + savedFilePath = shellCall?.toolResponse?.result?.outputFile; expect( savedFilePath, - `Expected to find a saved output file >= 20MB in ${tmpdir}`, + `Expected the tool response to contain an outputFile`, ).toBeTruthy(); + const savedContent = fs.readFileSync(savedFilePath, 'utf8'); expect(savedContent).toContain(startMarker); expect(savedContent).toContain(endMarker); diff --git a/packages/core/src/tools/shell.ts b/packages/core/src/tools/shell.ts index 50170f8ce4..8dabc9296b 100644 --- a/packages/core/src/tools/shell.ts +++ b/packages/core/src/tools/shell.ts @@ -466,7 +466,9 @@ export class ShellToolInvocation extends BaseToolInvocation< const onAbort = () => combinedController.abort(); const outputFileName = `gemini_shell_output_${crypto.randomBytes(6).toString('hex')}.log`; - const outputFilePath = path.join(os.tmpdir(), outputFileName); + const projectTempDir = this.context.config.storage.getProjectTempDir(); + fs.mkdirSync(projectTempDir, { recursive: true }); + const outputFilePath = path.join(projectTempDir, outputFileName); const outputStream = fs.createWriteStream(outputFilePath); let fullOutputReturned = false; @@ -669,7 +671,8 @@ export class ShellToolInvocation extends BaseToolInvocation< } const result = await resultPromise; - await new Promise((resolve) => { + await new Promise((resolve, reject) => { + outputStream.on('error', reject); outputStream.end(resolve); });