Log when flash model decided to continue (#4698)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Sandy Tao 2025-07-22 17:31:57 -07:00 committed by GitHub
parent 30c68922a3
commit 67008d4643
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 1 deletions

View File

@ -198,6 +198,7 @@ describe('Gemini Client (client.ts)', () => {
getQuotaErrorOccurred: vi.fn().mockReturnValue(false), getQuotaErrorOccurred: vi.fn().mockReturnValue(false),
setQuotaErrorOccurred: vi.fn(), setQuotaErrorOccurred: vi.fn(),
getNoBrowser: vi.fn().mockReturnValue(false), getNoBrowser: vi.fn().mockReturnValue(false),
getUsageStatisticsEnabled: vi.fn().mockReturnValue(true),
getIdeMode: vi.fn().mockReturnValue(false), getIdeMode: vi.fn().mockReturnValue(false),
getGeminiClient: vi.fn(), getGeminiClient: vi.fn(),
}; };

View File

@ -43,6 +43,8 @@ import { ProxyAgent, setGlobalDispatcher } from 'undici';
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js'; import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
import { LoopDetectionService } from '../services/loopDetectionService.js'; import { LoopDetectionService } from '../services/loopDetectionService.js';
import { ideContext } from '../services/ideContext.js'; import { ideContext } from '../services/ideContext.js';
import { ClearcutLogger } from '../telemetry/clearcut-logger/clearcut-logger.js';
import { FlashDecidedToContinueEvent } from '../telemetry/types.js';
function isThinkingSupported(model: string) { function isThinkingSupported(model: string) {
if (model.startsWith('gemini-2.5')) return true; if (model.startsWith('gemini-2.5')) return true;
@ -386,6 +388,9 @@ export class GeminiClient {
signal, signal,
); );
if (nextSpeakerCheck?.next_speaker === 'model') { if (nextSpeakerCheck?.next_speaker === 'model') {
ClearcutLogger.getInstance(this.config)?.logFlashDecidedToContinueEvent(
new FlashDecidedToContinueEvent(prompt_id),
);
const nextRequest = [{ text: 'Please continue.' }]; const nextRequest = [{ text: 'Please continue.' }];
// This recursive call's events will be yielded out, but the final // This recursive call's events will be yielded out, but the final
// turn object will be from the top-level call. // turn object will be from the top-level call.

View File

@ -18,6 +18,7 @@ import {
ApiErrorEvent, ApiErrorEvent,
FlashFallbackEvent, FlashFallbackEvent,
LoopDetectedEvent, LoopDetectedEvent,
FlashDecidedToContinueEvent,
} from '../types.js'; } from '../types.js';
import { EventMetadataKey } from './event-metadata-key.js'; import { EventMetadataKey } from './event-metadata-key.js';
import { Config } from '../../config/config.js'; import { Config } from '../../config/config.js';
@ -37,6 +38,7 @@ const api_error_event_name = 'api_error';
const end_session_event_name = 'end_session'; const end_session_event_name = 'end_session';
const flash_fallback_event_name = 'flash_fallback'; const flash_fallback_event_name = 'flash_fallback';
const loop_detected_event_name = 'loop_detected'; const loop_detected_event_name = 'loop_detected';
const flash_decided_to_continue_event_name = 'flash_decided_to_continue';
export interface LogResponse { export interface LogResponse {
nextRequestWaitMs?: number; nextRequestWaitMs?: number;
@ -492,6 +494,24 @@ export class ClearcutLogger {
this.flushIfNeeded(); this.flushIfNeeded();
} }
logFlashDecidedToContinueEvent(event: FlashDecidedToContinueEvent): void {
const data = [
{
gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
value: JSON.stringify(event.prompt_id),
},
{
gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
value: this.config?.getSessionId() ?? '',
},
];
this.enqueueLogEvent(
this.createLogEvent(flash_decided_to_continue_event_name, data),
);
this.flushIfNeeded();
}
logEndSessionEvent(event: EndSessionEvent): void { logEndSessionEvent(event: EndSessionEvent): void {
const data = [ const data = [
{ {

View File

@ -264,6 +264,18 @@ export class LoopDetectedEvent {
} }
} }
export class FlashDecidedToContinueEvent {
'event.name': 'flash_decided_to_continue';
'event.timestamp': string; // ISO 8601
prompt_id: string;
constructor(prompt_id: string) {
this['event.name'] = 'flash_decided_to_continue';
this['event.timestamp'] = new Date().toISOString();
this.prompt_id = prompt_id;
}
}
export type TelemetryEvent = export type TelemetryEvent =
| StartSessionEvent | StartSessionEvent
| EndSessionEvent | EndSessionEvent
@ -273,4 +285,5 @@ export type TelemetryEvent =
| ApiErrorEvent | ApiErrorEvent
| ApiResponseEvent | ApiResponseEvent
| FlashFallbackEvent | FlashFallbackEvent
| LoopDetectedEvent; | LoopDetectedEvent
| FlashDecidedToContinueEvent;