mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-15 06:12:50 -07:00
Checkpoint of shell optimization
fix(cli): Write shell command output to a file and limit memory buffered in UI Fixes. Checkpoint. fix(core, cli): await outputStream.end() to prevent race conditions This commit fixes a critical race condition where was called synchronously without being awaited. This led to potential file truncation or EBUSY errors on Windows when attempting to manipulate the file immediately after the call. Additionally, this change removes fixed wait times (`setTimeout`) that were previously used in test files as a band-aid. fix(core): stream processed xterm output to file to remove spurious escape codes test(core): update shell regression tests to use file_data events
This commit is contained in:
@@ -182,25 +182,47 @@ export class ToolOutputMaskingService {
|
||||
|
||||
const toolName = part.functionResponse.name || 'unknown_tool';
|
||||
const callId = part.functionResponse.id || Date.now().toString();
|
||||
const safeToolName = sanitizeFilenamePart(toolName).toLowerCase();
|
||||
const safeCallId = sanitizeFilenamePart(callId).toLowerCase();
|
||||
const fileName = `${safeToolName}_${safeCallId}_${Math.random()
|
||||
.toString(36)
|
||||
.substring(7)}.txt`;
|
||||
const filePath = path.join(toolOutputsDir, fileName);
|
||||
|
||||
await fsPromises.writeFile(filePath, content, 'utf-8');
|
||||
|
||||
const originalResponse =
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
||||
(part.functionResponse.response as Record<string, unknown>) || {};
|
||||
|
||||
const totalLines = content.split('\n').length;
|
||||
const fileSizeMB = (
|
||||
Buffer.byteLength(content, 'utf8') /
|
||||
1024 /
|
||||
1024
|
||||
).toFixed(2);
|
||||
let filePath = '';
|
||||
let fileSizeMB = '0.00';
|
||||
let totalLines = 0;
|
||||
|
||||
if (
|
||||
typeof originalResponse['outputFile'] === 'string' &&
|
||||
originalResponse['outputFile']
|
||||
) {
|
||||
filePath = originalResponse['outputFile'];
|
||||
try {
|
||||
const stats = await fsPromises.stat(filePath);
|
||||
fileSizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
||||
// For truly full files, we don't count lines as it's too slow.
|
||||
// We just indicate it's the full file.
|
||||
totalLines = -1;
|
||||
} catch {
|
||||
// Fallback if file is gone
|
||||
filePath = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!filePath) {
|
||||
const safeToolName = sanitizeFilenamePart(toolName).toLowerCase();
|
||||
const safeCallId = sanitizeFilenamePart(callId).toLowerCase();
|
||||
const fileName = `${safeToolName}_${safeCallId}_${Math.random()
|
||||
.toString(36)
|
||||
.substring(7)}.txt`;
|
||||
filePath = path.join(toolOutputsDir, fileName);
|
||||
|
||||
await fsPromises.writeFile(filePath, content, 'utf-8');
|
||||
|
||||
totalLines = content.split('\n').length;
|
||||
fileSizeMB = (Buffer.byteLength(content, 'utf8') / 1024 / 1024).toFixed(
|
||||
2,
|
||||
);
|
||||
}
|
||||
|
||||
let preview = '';
|
||||
if (toolName === SHELL_TOOL_NAME) {
|
||||
|
||||
Reference in New Issue
Block a user