Fix mixed input crash by adding proper error handling 8304 (#8430)

This commit is contained in:
fuyou
2025-09-16 06:56:25 +08:00
committed by GitHub
parent 12f584fff8
commit 079526fd3b
3 changed files with 80 additions and 8 deletions

View File

@@ -0,0 +1,62 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect } from 'vitest';
import { TestRig } from './test-helper.js';
describe('mixed input crash prevention', () => {
it('should not crash when using mixed prompt inputs', async () => {
const rig = new TestRig();
rig.setup('should not crash when using mixed prompt inputs');
// Test: echo "say '1'." | gemini --prompt-interactive="say '2'." say '3'.
const stdinContent = "say '1'.";
try {
await rig.run(
{ stdin: stdinContent },
'--prompt-interactive',
"say '2'.",
"say '3'.",
);
throw new Error('Expected the command to fail, but it succeeded');
} catch (error: unknown) {
expect(error).toBeInstanceOf(Error);
const err = error as Error;
expect(err.message).toContain('Process exited with code 1');
expect(err.message).toContain(
'--prompt-interactive flag cannot be used when input is piped',
);
expect(err.message).not.toContain('setRawMode is not a function');
expect(err.message).not.toContain('unexpected critical error');
}
const lastRequest = rig.readLastApiRequest();
expect(lastRequest).toBeNull();
});
it('should provide clear error message for mixed input', async () => {
const rig = new TestRig();
rig.setup('should provide clear error message for mixed input');
try {
await rig.run(
{ stdin: 'test input' },
'--prompt-interactive',
'test prompt',
);
throw new Error('Expected the command to fail, but it succeeded');
} catch (error: unknown) {
expect(error).toBeInstanceOf(Error);
const err = error as Error;
expect(err.message).toContain(
'--prompt-interactive flag cannot be used when input is piped',
);
}
});
});

View File

@@ -174,6 +174,15 @@ describe('gemini.tsx main function kitty protocol', () => {
(process.stdin as any).setRawMode = vi.fn();
}
setRawModeSpy = vi.spyOn(process.stdin, 'setRawMode');
Object.defineProperty(process.stdin, 'isTTY', {
value: true,
configurable: true,
});
Object.defineProperty(process.stdin, 'isRaw', {
value: false,
configurable: true,
});
});
it('should call setRawMode and detectAndEnableKittyProtocol when isInteractive is true', async () => {

View File

@@ -209,9 +209,17 @@ export async function main() {
argv,
);
// Check for invalid input combinations early to prevent crashes
if (argv.promptInteractive && !process.stdin.isTTY) {
console.error(
'Error: The --prompt-interactive flag cannot be used when input is piped from stdin.',
);
process.exit(1);
}
const wasRaw = process.stdin.isRaw;
let kittyProtocolDetectionComplete: Promise<boolean> | undefined;
if (config.isInteractive() && !wasRaw) {
if (config.isInteractive() && !wasRaw && process.stdin.isTTY) {
// Set this as early as possible to avoid spurious characters from
// input showing up in the output.
process.stdin.setRawMode(true);
@@ -248,13 +256,6 @@ export async function main() {
validateDnsResolutionOrder(settings.merged.advanced?.dnsResolutionOrder),
);
if (argv.promptInteractive && !process.stdin.isTTY) {
console.error(
'Error: The --prompt-interactive flag is not supported when piping input from stdin.',
);
process.exit(1);
}
if (config.getListExtensions()) {
console.log('Installed extensions:');
for (const extension of extensions) {