mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-02 18:47:06 +00:00
Structured JSON Output (#8119)
This commit is contained in:
@@ -1972,6 +1972,55 @@ describe('loadCliConfig fileFiltering', () => {
|
||||
);
|
||||
});
|
||||
|
||||
describe('Output Format Configuration', () => {
|
||||
const originalArgv = process.argv;
|
||||
|
||||
afterEach(() => {
|
||||
process.argv = originalArgv;
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('should default to text format when no setting or flag is provided', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const argv = await parseArguments({} as Settings);
|
||||
const config = await loadCliConfig(
|
||||
{} as Settings,
|
||||
[],
|
||||
'test-session',
|
||||
argv,
|
||||
);
|
||||
expect(config.getOutputFormat()).toBe(ServerConfig.OutputFormat.TEXT);
|
||||
});
|
||||
|
||||
it('should use the format from settings when no flag is provided', async () => {
|
||||
process.argv = ['node', 'script.js'];
|
||||
const settings: Settings = { output: { format: 'json' } };
|
||||
const argv = await parseArguments(settings);
|
||||
const config = await loadCliConfig(settings, [], 'test-session', argv);
|
||||
expect(config.getOutputFormat()).toBe(ServerConfig.OutputFormat.JSON);
|
||||
});
|
||||
|
||||
it('should use the format from the flag when provided', async () => {
|
||||
process.argv = ['node', 'script.js', '--output-format', 'json'];
|
||||
const argv = await parseArguments({} as Settings);
|
||||
const config = await loadCliConfig(
|
||||
{} as Settings,
|
||||
[],
|
||||
'test-session',
|
||||
argv,
|
||||
);
|
||||
expect(config.getOutputFormat()).toBe(ServerConfig.OutputFormat.JSON);
|
||||
});
|
||||
|
||||
it('should prioritize the flag over the setting', async () => {
|
||||
process.argv = ['node', 'script.js', '--output-format', 'text'];
|
||||
const settings: Settings = { output: { format: 'json' } };
|
||||
const argv = await parseArguments(settings);
|
||||
const config = await loadCliConfig(settings, [], 'test-session', argv);
|
||||
expect(config.getOutputFormat()).toBe(ServerConfig.OutputFormat.TEXT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseArguments with positional prompt', () => {
|
||||
const originalArgv = process.argv;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import type {
|
||||
TelemetryTarget,
|
||||
FileFilteringOptions,
|
||||
MCPServerConfig,
|
||||
OutputFormat,
|
||||
} from '@google/gemini-cli-core';
|
||||
import { extensionsCommand } from '../commands/extensions.js';
|
||||
import {
|
||||
@@ -81,6 +82,7 @@ export interface CliArgs {
|
||||
useSmartEdit: boolean | undefined;
|
||||
sessionSummary: string | undefined;
|
||||
promptWords: string[] | undefined;
|
||||
outputFormat: string | undefined;
|
||||
}
|
||||
|
||||
export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
@@ -234,6 +236,11 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
type: 'string',
|
||||
description: 'File to write session summary to.',
|
||||
})
|
||||
.option('output-format', {
|
||||
type: 'string',
|
||||
description: 'The format of the CLI output.',
|
||||
choices: ['text', 'json'],
|
||||
})
|
||||
.deprecateOption(
|
||||
'telemetry',
|
||||
'Use the "telemetry.enabled" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
@@ -627,6 +634,9 @@ export async function loadCliConfig(
|
||||
enableToolOutputTruncation: settings.tools?.enableToolOutputTruncation,
|
||||
eventEmitter: appEvents,
|
||||
useSmartEdit: argv.useSmartEdit ?? settings.useSmartEdit,
|
||||
output: {
|
||||
format: (argv.outputFormat ?? settings.output?.format) as OutputFormat,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1078,6 +1078,30 @@ describe('Settings Loading and Merging', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should merge output format settings, with workspace taking precedence', () => {
|
||||
(mockFsExistsSync as Mock).mockReturnValue(true);
|
||||
const userSettingsContent = {
|
||||
output: { format: 'text' },
|
||||
};
|
||||
const workspaceSettingsContent = {
|
||||
output: { format: 'json' },
|
||||
};
|
||||
|
||||
(fs.readFileSync as Mock).mockImplementation(
|
||||
(p: fs.PathOrFileDescriptor) => {
|
||||
if (p === USER_SETTINGS_PATH)
|
||||
return JSON.stringify(userSettingsContent);
|
||||
if (p === MOCK_WORKSPACE_SETTINGS_PATH)
|
||||
return JSON.stringify(workspaceSettingsContent);
|
||||
return '{}';
|
||||
},
|
||||
);
|
||||
|
||||
const settings = loadSettings(MOCK_WORKSPACE_DIR);
|
||||
|
||||
expect(settings.merged.output?.format).toBe('json');
|
||||
});
|
||||
|
||||
it('should handle chatCompression when only in user settings', () => {
|
||||
(mockFsExistsSync as Mock).mockImplementation(
|
||||
(p: fs.PathLike) => p === USER_SETTINGS_PATH,
|
||||
|
||||
@@ -187,6 +187,30 @@ const SETTINGS_SCHEMA = {
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
type: 'object',
|
||||
label: 'Output',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
default: {},
|
||||
description: 'Settings for the CLI output.',
|
||||
showInDialog: false,
|
||||
properties: {
|
||||
format: {
|
||||
type: 'enum',
|
||||
label: 'Output Format',
|
||||
category: 'General',
|
||||
requiresRestart: false,
|
||||
default: 'text',
|
||||
description: 'The format of the CLI output.',
|
||||
showInDialog: true,
|
||||
options: [
|
||||
{ value: 'text', label: 'Text' },
|
||||
{ value: 'json', label: 'JSON' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
ui: {
|
||||
type: 'object',
|
||||
|
||||
Reference in New Issue
Block a user