mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-19 09:41:17 -07:00
fix(core): remove shell outputChunks buffer caching to prevent memory bloat and sanitize prompt input (#23751)
This commit is contained in:
@@ -120,7 +120,8 @@ interface ActiveChildProcess {
|
||||
state: {
|
||||
output: string;
|
||||
truncated: boolean;
|
||||
outputChunks: Buffer[];
|
||||
sniffChunks: Buffer[];
|
||||
binaryBytesReceived: number;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -493,7 +494,8 @@ export class ShellExecutionService {
|
||||
const state = {
|
||||
output: '',
|
||||
truncated: false,
|
||||
outputChunks: [] as Buffer[],
|
||||
sniffChunks: [] as Buffer[],
|
||||
binaryBytesReceived: 0,
|
||||
};
|
||||
|
||||
if (child.pid) {
|
||||
@@ -563,14 +565,19 @@ export class ShellExecutionService {
|
||||
}
|
||||
}
|
||||
|
||||
state.outputChunks.push(data);
|
||||
if (isStreamingRawContent && sniffedBytes < MAX_SNIFF_SIZE) {
|
||||
state.sniffChunks.push(data);
|
||||
} else if (!isStreamingRawContent) {
|
||||
state.binaryBytesReceived += data.length;
|
||||
}
|
||||
|
||||
if (isStreamingRawContent && sniffedBytes < MAX_SNIFF_SIZE) {
|
||||
const sniffBuffer = Buffer.concat(state.outputChunks.slice(0, 20));
|
||||
const sniffBuffer = Buffer.concat(state.sniffChunks.slice(0, 20));
|
||||
sniffedBytes = sniffBuffer.length;
|
||||
|
||||
if (isBinary(sniffBuffer)) {
|
||||
isStreamingRawContent = false;
|
||||
state.binaryBytesReceived = sniffBuffer.length;
|
||||
const event: ShellOutputEvent = { type: 'binary_detected' };
|
||||
onOutputEvent(event);
|
||||
if (child.pid) {
|
||||
@@ -610,10 +617,7 @@ export class ShellExecutionService {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const totalBytes = state.outputChunks.reduce(
|
||||
(sum, chunk) => sum + chunk.length,
|
||||
0,
|
||||
);
|
||||
const totalBytes = state.binaryBytesReceived;
|
||||
const event: ShellOutputEvent = {
|
||||
type: 'binary_progress',
|
||||
bytesReceived: totalBytes,
|
||||
@@ -629,7 +633,7 @@ export class ShellExecutionService {
|
||||
code: number | null,
|
||||
signal: NodeJS.Signals | null,
|
||||
) => {
|
||||
const { finalBuffer } = cleanup();
|
||||
cleanup();
|
||||
|
||||
let combinedOutput = state.output;
|
||||
if (state.truncated) {
|
||||
@@ -644,7 +648,7 @@ export class ShellExecutionService {
|
||||
const exitSignal = signal ? os.constants.signals[signal] : null;
|
||||
|
||||
const resultPayload: ShellExecutionResult = {
|
||||
rawOutput: finalBuffer,
|
||||
rawOutput: Buffer.from(''),
|
||||
output: finalStrippedOutput,
|
||||
exitCode,
|
||||
signal: exitSignal,
|
||||
@@ -733,8 +737,7 @@ export class ShellExecutionService {
|
||||
}
|
||||
}
|
||||
|
||||
const finalBuffer = Buffer.concat(state.outputChunks);
|
||||
return { finalBuffer };
|
||||
return;
|
||||
}
|
||||
|
||||
return { pid: child.pid, result };
|
||||
@@ -864,7 +867,8 @@ export class ShellExecutionService {
|
||||
let processingChain = Promise.resolve();
|
||||
let decoder: TextDecoder | null = null;
|
||||
let output: string | AnsiOutput | null = null;
|
||||
const outputChunks: Buffer[] = [];
|
||||
const sniffChunks: Buffer[] = [];
|
||||
let binaryBytesReceived = 0;
|
||||
const error: Error | null = null;
|
||||
let exited = false;
|
||||
|
||||
@@ -995,14 +999,19 @@ export class ShellExecutionService {
|
||||
}
|
||||
}
|
||||
|
||||
outputChunks.push(data);
|
||||
if (isStreamingRawContent && sniffedBytes < MAX_SNIFF_SIZE) {
|
||||
sniffChunks.push(data);
|
||||
} else if (!isStreamingRawContent) {
|
||||
binaryBytesReceived += data.length;
|
||||
}
|
||||
|
||||
if (isStreamingRawContent && sniffedBytes < MAX_SNIFF_SIZE) {
|
||||
const sniffBuffer = Buffer.concat(outputChunks.slice(0, 20));
|
||||
const sniffBuffer = Buffer.concat(sniffChunks.slice(0, 20));
|
||||
sniffedBytes = sniffBuffer.length;
|
||||
|
||||
if (isBinary(sniffBuffer)) {
|
||||
isStreamingRawContent = false;
|
||||
binaryBytesReceived = sniffBuffer.length;
|
||||
const event: ShellOutputEvent = { type: 'binary_detected' };
|
||||
onOutputEvent(event);
|
||||
ExecutionLifecycleService.emitEvent(ptyPid, event);
|
||||
@@ -1027,10 +1036,7 @@ export class ShellExecutionService {
|
||||
resolveChunk();
|
||||
});
|
||||
} else {
|
||||
const totalBytes = outputChunks.reduce(
|
||||
(sum, chunk) => sum + chunk.length,
|
||||
0,
|
||||
);
|
||||
const totalBytes = binaryBytesReceived;
|
||||
const event: ShellOutputEvent = {
|
||||
type: 'binary_progress',
|
||||
bytesReceived: totalBytes,
|
||||
@@ -1076,7 +1082,7 @@ export class ShellExecutionService {
|
||||
});
|
||||
|
||||
ExecutionLifecycleService.completeWithResult(ptyPid, {
|
||||
rawOutput: Buffer.concat(outputChunks),
|
||||
rawOutput: Buffer.from(''),
|
||||
output: getFullBufferText(headlessTerminal),
|
||||
exitCode,
|
||||
signal: signal ?? null,
|
||||
|
||||
Reference in New Issue
Block a user