fix(cli)!: Default to interactive mode for positional arguments (#16329)

Co-authored-by: Allen Hutchison <adh@google.com>
This commit is contained in:
Ishaan Gupta
2026-01-23 05:08:53 +05:30
committed by GitHub
parent a060e6149a
commit beacc4f6fd
3 changed files with 53 additions and 24 deletions
+32 -14
View File
@@ -371,6 +371,21 @@ describe('parseArguments', () => {
}
},
);
it('should include a startup message when converting positional query to interactive prompt', async () => {
const originalIsTTY = process.stdin.isTTY;
process.stdin.isTTY = true;
process.argv = ['node', 'script.js', 'hello'];
try {
const argv = await parseArguments(createTestMergedSettings());
expect(argv.startupMessages).toContain(
'Positional arguments now default to interactive mode. To run in non-interactive mode, use the --prompt (-p) flag.',
);
} finally {
process.stdin.isTTY = originalIsTTY;
}
});
});
it.each([
@@ -1953,7 +1968,7 @@ describe('loadCliConfig interactive', () => {
expect(config.isInteractive()).toBe(false);
});
it('should not be interactive if positional prompt words are provided with other flags', async () => {
it('should be interactive if positional prompt words are provided with other flags', async () => {
process.stdin.isTTY = true;
process.argv = ['node', 'script.js', '--model', 'gemini-2.5-pro', 'Hello'];
const argv = await parseArguments(createTestMergedSettings());
@@ -1962,10 +1977,10 @@ describe('loadCliConfig interactive', () => {
'test-session',
argv,
);
expect(config.isInteractive()).toBe(false);
expect(config.isInteractive()).toBe(true);
});
it('should not be interactive if positional prompt words are provided with multiple flags', async () => {
it('should be interactive if positional prompt words are provided with multiple flags', async () => {
process.stdin.isTTY = true;
process.argv = [
'node',
@@ -1981,13 +1996,13 @@ describe('loadCliConfig interactive', () => {
'test-session',
argv,
);
expect(config.isInteractive()).toBe(false);
expect(config.isInteractive()).toBe(true);
// Verify the question is preserved for one-shot execution
expect(argv.prompt).toBe('Hello world');
expect(argv.promptInteractive).toBeUndefined();
expect(argv.prompt).toBeUndefined();
expect(argv.promptInteractive).toBe('Hello world');
});
it('should not be interactive if positional prompt words are provided with extensions flag', async () => {
it('should be interactive if positional prompt words are provided with extensions flag', async () => {
process.stdin.isTTY = true;
process.argv = ['node', 'script.js', '-e', 'none', 'hello'];
const argv = await parseArguments(createTestMergedSettings());
@@ -1996,8 +2011,9 @@ describe('loadCliConfig interactive', () => {
'test-session',
argv,
);
expect(config.isInteractive()).toBe(false);
expect(config.isInteractive()).toBe(true);
expect(argv.query).toBe('hello');
expect(argv.promptInteractive).toBe('hello');
expect(argv.extensions).toEqual(['none']);
});
@@ -2010,9 +2026,9 @@ describe('loadCliConfig interactive', () => {
'test-session',
argv,
);
expect(config.isInteractive()).toBe(false);
expect(config.isInteractive()).toBe(true);
expect(argv.query).toBe('hello world how are you');
expect(argv.prompt).toBe('hello world how are you');
expect(argv.promptInteractive).toBe('hello world how are you');
});
it('should handle multiple positional words with flags', async () => {
@@ -2035,8 +2051,9 @@ describe('loadCliConfig interactive', () => {
'test-session',
argv,
);
expect(config.isInteractive()).toBe(false);
expect(config.isInteractive()).toBe(true);
expect(argv.query).toBe('write a function to sort array');
expect(argv.promptInteractive).toBe('write a function to sort array');
expect(argv.model).toBe('gemini-2.5-pro');
});
@@ -2072,8 +2089,9 @@ describe('loadCliConfig interactive', () => {
'test-session',
argv,
);
expect(config.isInteractive()).toBe(false);
expect(config.isInteractive()).toBe(true);
expect(argv.query).toBe('hello world how are you');
expect(argv.promptInteractive).toBe('hello world how are you');
expect(argv.extensions).toEqual(['none']);
});
@@ -2708,9 +2726,9 @@ describe('PolicyEngine nonInteractive wiring', () => {
vi.restoreAllMocks();
});
it('should set nonInteractive to true in one-shot mode', async () => {
it('should set nonInteractive to true when -p flag is used', async () => {
process.stdin.isTTY = true;
process.argv = ['node', 'script.js', 'echo hello']; // Positional query makes it one-shot
process.argv = ['node', 'script.js', '-p', 'echo hello'];
const argv = await parseArguments(createTestMergedSettings());
const config = await loadCliConfig(
createTestMergedSettings(),