| |
| |
| |
| |
| |
|
|
| import { debugLogger } from '@google/gemini-cli-core'; |
|
|
| |
| |
| |
| |
| |
| function truncateUtf8Bytes(str: string, maxBytes: number): string { |
| const buf = Buffer.from(str, 'utf8'); |
| if (buf.length <= maxBytes) return str; |
| let end = maxBytes; |
| |
| while (end > 0 && (buf[end] & 0xc0) === 0x80) { |
| end--; |
| } |
| |
| return buf.subarray(0, end).toString('utf8'); |
| } |
|
|
| export async function readStdin(): Promise<string> { |
| const MAX_STDIN_SIZE = 8 * 1024 * 1024; |
| return new Promise((resolve, reject) => { |
| let data = ''; |
| let totalSize = 0; |
| process.stdin.setEncoding('utf8'); |
|
|
| const pipedInputShouldBeAvailableInMs = 500; |
| let pipedInputTimerId: null | NodeJS.Timeout = setTimeout(() => { |
| |
| |
| |
| onEnd(); |
| }, pipedInputShouldBeAvailableInMs); |
|
|
| const onReadable = () => { |
| let chunk; |
| |
| while ((chunk = process.stdin.read()) !== null) { |
| if (pipedInputTimerId) { |
| clearTimeout(pipedInputTimerId); |
| pipedInputTimerId = null; |
| } |
|
|
| const chunkByteLength = Buffer.byteLength(chunk, 'utf8'); |
| if (totalSize + chunkByteLength > MAX_STDIN_SIZE) { |
| const remainingBytes = MAX_STDIN_SIZE - totalSize; |
| data += truncateUtf8Bytes(chunk, remainingBytes); |
| debugLogger.warn( |
| `Warning: stdin input truncated to ${MAX_STDIN_SIZE} bytes.`, |
| ); |
| process.stdin.destroy(); |
| onEnd(); |
| break; |
| } |
| data += chunk; |
| totalSize += chunkByteLength; |
| } |
| }; |
|
|
| const onEnd = () => { |
| cleanup(); |
| resolve(data); |
| }; |
|
|
| const onError = (err: Error) => { |
| cleanup(); |
| reject(err); |
| }; |
|
|
| const cleanup = () => { |
| if (pipedInputTimerId) { |
| clearTimeout(pipedInputTimerId); |
| pipedInputTimerId = null; |
| } |
| process.stdin.removeListener('readable', onReadable); |
| process.stdin.removeListener('end', onEnd); |
| process.stdin.removeListener('error', onError); |
|
|
| |
| |
| |
| if (process.stdin.listenerCount('error') === 0) { |
| process.stdin.on('error', noopErrorHandler); |
| } |
| }; |
|
|
| process.stdin.on('readable', onReadable); |
| process.stdin.on('end', onEnd); |
| process.stdin.on('error', onError); |
| }); |
| } |
|
|
| function noopErrorHandler() {} |
|
|