mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-20 16:53:12 -07:00
fix(cli): preserve max-turns non-interactive parity
This commit is contained in:
committed by
Adam Weidman
parent
6795567d28
commit
1088e1febf
@@ -8,6 +8,14 @@ exports[`runNonInteractive > should emit appropriate error event in streaming JS
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`runNonInteractive > should emit appropriate error event in streaming JSON mode: 'max session turns' 1`] = `
|
||||
"{"type":"init","timestamp":"<TIMESTAMP>","session_id":"test-session-id","model":"test-model"}
|
||||
{"type":"message","timestamp":"<TIMESTAMP>","role":"user","content":"Max turns test"}
|
||||
{"type":"error","timestamp":"<TIMESTAMP>","severity":"error","message":"Maximum session turns exceeded"}
|
||||
{"type":"result","timestamp":"<TIMESTAMP>","status":"success","stats":{"total_tokens":0,"input_tokens":0,"output_tokens":0,"cached":0,"input":0,"duration_ms":<DURATION>,"tool_calls":0,"models":{}}}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`runNonInteractive > should emit appropriate events for streaming JSON output 1`] = `
|
||||
"{"type":"init","timestamp":"<TIMESTAMP>","session_id":"test-session-id","model":"test-model"}
|
||||
{"type":"message","timestamp":"<TIMESTAMP>","role":"user","content":"Stream test"}
|
||||
|
||||
@@ -679,21 +679,6 @@ describe('runNonInteractive', () => {
|
||||
).rejects.toThrow('process.exit(53) called');
|
||||
});
|
||||
|
||||
it('should exit when the session reports max turns through agent_end', async () => {
|
||||
mockGeminiClient.sendMessageStream.mockReturnValue(
|
||||
createStreamFromEvents([{ type: GeminiEventType.MaxSessionTurns }]),
|
||||
);
|
||||
|
||||
await expect(
|
||||
runNonInteractive({
|
||||
config: mockConfig,
|
||||
settings: mockSettings,
|
||||
input: 'Trigger max turns event',
|
||||
prompt_id: 'prompt-id-max-turns-event',
|
||||
}),
|
||||
).rejects.toThrow('process.exit(53) called');
|
||||
});
|
||||
|
||||
it('should preprocess @include commands before sending to the model', async () => {
|
||||
// 1. Mock the imported atCommandProcessor
|
||||
const { handleAtCommand } = await import(
|
||||
@@ -1855,9 +1840,17 @@ describe('runNonInteractive', () => {
|
||||
input: 'Loop test',
|
||||
promptId: 'prompt-id-loop',
|
||||
},
|
||||
{
|
||||
name: 'max session turns',
|
||||
events: [
|
||||
{ type: GeminiEventType.MaxSessionTurns },
|
||||
] as ServerGeminiStreamEvent[],
|
||||
input: 'Max turns test',
|
||||
promptId: 'prompt-id-max-turns',
|
||||
},
|
||||
])(
|
||||
'should emit appropriate error event in streaming JSON mode: $name',
|
||||
async ({ name, events, input, promptId }) => {
|
||||
async ({ events, input, promptId }) => {
|
||||
vi.mocked(mockConfig.getOutputFormat).mockReturnValue(
|
||||
OutputFormat.STREAM_JSON,
|
||||
);
|
||||
@@ -1895,52 +1888,6 @@ describe('runNonInteractive', () => {
|
||||
},
|
||||
);
|
||||
|
||||
it('should emit a terminal max-turns error event in streaming JSON mode', async () => {
|
||||
vi.mocked(mockConfig.getOutputFormat).mockReturnValue(
|
||||
OutputFormat.STREAM_JSON,
|
||||
);
|
||||
vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(
|
||||
MOCK_SESSION_METRICS,
|
||||
);
|
||||
|
||||
mockGeminiClient.sendMessageStream.mockReturnValue(
|
||||
createStreamFromEvents([
|
||||
{ type: GeminiEventType.MaxSessionTurns },
|
||||
{
|
||||
type: GeminiEventType.Finished,
|
||||
value: { reason: undefined, usageMetadata: { totalTokenCount: 0 } },
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
try {
|
||||
await runNonInteractive({
|
||||
config: mockConfig,
|
||||
settings: mockSettings,
|
||||
input: 'Max turns test',
|
||||
prompt_id: 'prompt-id-max-turns',
|
||||
});
|
||||
} catch (_error) {
|
||||
// Expected exit
|
||||
}
|
||||
|
||||
const streamEvents = getWrittenOutput()
|
||||
.trim()
|
||||
.split('\n')
|
||||
.map((line) => JSON.parse(line) as Record<string, unknown>);
|
||||
|
||||
expect(streamEvents).toHaveLength(3);
|
||||
expect(streamEvents[2]).toMatchObject({
|
||||
type: 'result',
|
||||
status: 'error',
|
||||
error: {
|
||||
type: 'FatalTurnLimitedError',
|
||||
message:
|
||||
'Reached max session turns for this session. Increase the number of turns by specifying maxSessionTurns in settings.json.',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should log error when tool recording fails', async () => {
|
||||
const toolCallEvent: ServerGeminiStreamEvent = {
|
||||
type: GeminiEventType.ToolCallRequest,
|
||||
|
||||
@@ -523,7 +523,20 @@ export async function runNonInteractive({
|
||||
if (event.reason === 'aborted') {
|
||||
runTerminalExitHandler(() => handleCancellationError(config));
|
||||
} else if (event.reason === 'max_turns') {
|
||||
runTerminalExitHandler(() => handleMaxTurnsExceededError(config));
|
||||
const isConfiguredTurnLimit =
|
||||
typeof event.data?.['maxTurns'] === 'number' ||
|
||||
typeof event.data?.['turnCount'] === 'number';
|
||||
|
||||
if (isConfiguredTurnLimit) {
|
||||
runTerminalExitHandler(() => handleMaxTurnsExceededError(config));
|
||||
} else if (streamFormatter) {
|
||||
streamFormatter.emitEvent({
|
||||
type: JsonStreamEventType.ERROR,
|
||||
timestamp: new Date().toISOString(),
|
||||
severity: 'error',
|
||||
message: 'Maximum session turns exceeded',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const stopMessage =
|
||||
|
||||
Reference in New Issue
Block a user