summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSandy Tao <[email protected]>2025-07-30 21:47:04 -0700
committerGitHub <[email protected]>2025-07-31 04:47:04 +0000
commit23c014e29cbb3ac28e6fb02ef14d0538377f38ca (patch)
tree704648d36543733dab4a29aca2d65d6fd74a4c5d
parent3ef2c6d19815769747b4970b7e4356d18e1af889 (diff)
Replace FlashDecidedToContinueEvent with NextSpeakerCheckEvent (#5257)
-rw-r--r--packages/core/src/core/client.ts16
-rw-r--r--packages/core/src/core/turn.ts3
-rw-r--r--packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts16
-rw-r--r--packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts10
-rw-r--r--packages/core/src/telemetry/constants.ts3
-rw-r--r--packages/core/src/telemetry/loggers.ts14
-rw-r--r--packages/core/src/telemetry/types.ts14
7 files changed, 52 insertions, 24 deletions
diff --git a/packages/core/src/core/client.ts b/packages/core/src/core/client.ts
index 49a30294..5b26e32c 100644
--- a/packages/core/src/core/client.ts
+++ b/packages/core/src/core/client.ts
@@ -43,8 +43,8 @@ import { ProxyAgent, setGlobalDispatcher } from 'undici';
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
import { LoopDetectionService } from '../services/loopDetectionService.js';
import { ideContext } from '../ide/ideContext.js';
-import { logFlashDecidedToContinue } from '../telemetry/loggers.js';
-import { FlashDecidedToContinueEvent } from '../telemetry/types.js';
+import { logNextSpeakerCheck } from '../telemetry/loggers.js';
+import { NextSpeakerCheckEvent } from '../telemetry/types.js';
function isThinkingSupported(model: string) {
if (model.startsWith('gemini-2.5')) return true;
@@ -415,11 +415,15 @@ export class GeminiClient {
this,
signal,
);
+ logNextSpeakerCheck(
+ this.config,
+ new NextSpeakerCheckEvent(
+ prompt_id,
+ turn.finishReason?.toString() || '',
+ nextSpeakerCheck?.next_speaker || '',
+ ),
+ );
if (nextSpeakerCheck?.next_speaker === 'model') {
- logFlashDecidedToContinue(
- this.config,
- new FlashDecidedToContinueEvent(prompt_id),
- );
const nextRequest = [{ text: 'Please continue.' }];
// This recursive call's events will be yielded out, but the final
// turn object will be from the top-level call.
diff --git a/packages/core/src/core/turn.ts b/packages/core/src/core/turn.ts
index bea29b66..b54b3f82 100644
--- a/packages/core/src/core/turn.ts
+++ b/packages/core/src/core/turn.ts
@@ -163,6 +163,7 @@ export type ServerGeminiStreamEvent =
export class Turn {
readonly pendingToolCalls: ToolCallRequestInfo[];
private debugResponses: GenerateContentResponse[];
+ finishReason: FinishReason | undefined;
constructor(
private readonly chat: GeminiChat,
@@ -170,6 +171,7 @@ export class Turn {
) {
this.pendingToolCalls = [];
this.debugResponses = [];
+ this.finishReason = undefined;
}
// The run method yields simpler events suitable for server logic
async *run(
@@ -235,6 +237,7 @@ export class Turn {
const finishReason = resp.candidates?.[0]?.finishReason;
if (finishReason) {
+ this.finishReason = finishReason;
yield {
type: GeminiEventType.Finished,
value: finishReason as FinishReason,
diff --git a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
index d221ef5e..81a9ca4b 100644
--- a/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
+++ b/packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
@@ -18,7 +18,7 @@ import {
ApiErrorEvent,
FlashFallbackEvent,
LoopDetectedEvent,
- FlashDecidedToContinueEvent,
+ NextSpeakerCheckEvent,
SlashCommandEvent,
} from '../types.js';
import { EventMetadataKey } from './event-metadata-key.js';
@@ -40,7 +40,7 @@ const api_error_event_name = 'api_error';
const end_session_event_name = 'end_session';
const flash_fallback_event_name = 'flash_fallback';
const loop_detected_event_name = 'loop_detected';
-const flash_decided_to_continue_event_name = 'flash_decided_to_continue';
+const next_speaker_check_event_name = 'next_speaker_check';
const slash_command_event_name = 'slash_command';
export interface LogResponse {
@@ -512,20 +512,28 @@ export class ClearcutLogger {
this.flushIfNeeded();
}
- logFlashDecidedToContinueEvent(event: FlashDecidedToContinueEvent): void {
+ logNextSpeakerCheck(event: NextSpeakerCheckEvent): void {
const data = [
{
gemini_cli_key: EventMetadataKey.GEMINI_CLI_PROMPT_ID,
value: JSON.stringify(event.prompt_id),
},
{
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_RESPONSE_FINISH_REASON,
+ value: JSON.stringify(event.finish_reason),
+ },
+ {
+ gemini_cli_key: EventMetadataKey.GEMINI_CLI_NEXT_SPEAKER_CHECK_RESULT,
+ value: JSON.stringify(event.result),
+ },
+ {
gemini_cli_key: EventMetadataKey.GEMINI_CLI_SESSION_ID,
value: this.config?.getSessionId() ?? '',
},
];
this.enqueueLogEvent(
- this.createLogEvent(flash_decided_to_continue_event_name, data),
+ this.createLogEvent(next_speaker_check_event_name, data),
);
this.flushIfNeeded();
}
diff --git a/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts b/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
index 9a182f67..01dd42af 100644
--- a/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
+++ b/packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
@@ -173,6 +173,16 @@ export enum EventMetadataKey {
// Logs the subcommand of the slash command.
GEMINI_CLI_SLASH_COMMAND_SUBCOMMAND = 42,
+
+ // ==========================================================================
+ // Next Speaker Check Event Keys
+ // ===========================================================================
+
+ // Logs the finish reason of the previous streamGenerateContent response
+ GEMINI_CLI_RESPONSE_FINISH_REASON = 43,
+
+ // Logs the result of the next speaker check
+ GEMINI_CLI_NEXT_SPEAKER_CHECK_RESULT = 44,
}
export function getEventMetadataKey(
diff --git a/packages/core/src/telemetry/constants.ts b/packages/core/src/telemetry/constants.ts
index 42572228..7dd5c8d1 100644
--- a/packages/core/src/telemetry/constants.ts
+++ b/packages/core/src/telemetry/constants.ts
@@ -13,8 +13,7 @@ export const EVENT_API_ERROR = 'gemini_cli.api_error';
export const EVENT_API_RESPONSE = 'gemini_cli.api_response';
export const EVENT_CLI_CONFIG = 'gemini_cli.config';
export const EVENT_FLASH_FALLBACK = 'gemini_cli.flash_fallback';
-export const EVENT_FLASH_DECIDED_TO_CONTINUE =
- 'gemini_cli.flash_decided_to_continue';
+export const EVENT_NEXT_SPEAKER_CHECK = 'gemini_cli.next_speaker_check';
export const EVENT_SLASH_COMMAND = 'gemini_cli.slash_command';
export const METRIC_TOOL_CALL_COUNT = 'gemini_cli.tool.call.count';
diff --git a/packages/core/src/telemetry/loggers.ts b/packages/core/src/telemetry/loggers.ts
index 3ee806bb..2aa0d86a 100644
--- a/packages/core/src/telemetry/loggers.ts
+++ b/packages/core/src/telemetry/loggers.ts
@@ -15,7 +15,7 @@ import {
EVENT_TOOL_CALL,
EVENT_USER_PROMPT,
EVENT_FLASH_FALLBACK,
- EVENT_FLASH_DECIDED_TO_CONTINUE,
+ EVENT_NEXT_SPEAKER_CHECK,
SERVICE_NAME,
EVENT_SLASH_COMMAND,
} from './constants.js';
@@ -27,7 +27,7 @@ import {
ToolCallEvent,
UserPromptEvent,
FlashFallbackEvent,
- FlashDecidedToContinueEvent,
+ NextSpeakerCheckEvent,
LoopDetectedEvent,
SlashCommandEvent,
} from './types.js';
@@ -314,22 +314,22 @@ export function logLoopDetected(
logger.emit(logRecord);
}
-export function logFlashDecidedToContinue(
+export function logNextSpeakerCheck(
config: Config,
- event: FlashDecidedToContinueEvent,
+ event: NextSpeakerCheckEvent,
): void {
- ClearcutLogger.getInstance(config)?.logFlashDecidedToContinueEvent(event);
+ ClearcutLogger.getInstance(config)?.logNextSpeakerCheck(event);
if (!isTelemetrySdkInitialized()) return;
const attributes: LogAttributes = {
...getCommonAttributes(config),
...event,
- 'event.name': EVENT_FLASH_DECIDED_TO_CONTINUE,
+ 'event.name': EVENT_NEXT_SPEAKER_CHECK,
};
const logger = logs.getLogger(SERVICE_NAME);
const logRecord: LogRecord = {
- body: `Flash decided to continue.`,
+ body: `Next speaker check.`,
attributes,
};
logger.emit(logRecord);
diff --git a/packages/core/src/telemetry/types.ts b/packages/core/src/telemetry/types.ts
index d29b97d2..6fe797bf 100644
--- a/packages/core/src/telemetry/types.ts
+++ b/packages/core/src/telemetry/types.ts
@@ -266,15 +266,19 @@ export class LoopDetectedEvent {
}
}
-export class FlashDecidedToContinueEvent {
- 'event.name': 'flash_decided_to_continue';
+export class NextSpeakerCheckEvent {
+ 'event.name': 'next_speaker_check';
'event.timestamp': string; // ISO 8601
prompt_id: string;
+ finish_reason: string;
+ result: string;
- constructor(prompt_id: string) {
- this['event.name'] = 'flash_decided_to_continue';
+ constructor(prompt_id: string, finish_reason: string, result: string) {
+ this['event.name'] = 'next_speaker_check';
this['event.timestamp'] = new Date().toISOString();
this.prompt_id = prompt_id;
+ this.finish_reason = finish_reason;
+ this.result = result;
}
}
@@ -302,5 +306,5 @@ export type TelemetryEvent =
| ApiResponseEvent
| FlashFallbackEvent
| LoopDetectedEvent
- | FlashDecidedToContinueEvent
+ | NextSpeakerCheckEvent
| SlashCommandEvent;