From 5eeddaef525e799f639ba6c8381955b84ea14a39 Mon Sep 17 00:00:00 2001 From: Adam Weidman Date: Mon, 9 Feb 2026 14:49:40 -0500 Subject: [PATCH] feat: instrument adaptive thinking metrics in telemetry and chat logs --- packages/core/src/core/client.ts | 5 +++ packages/core/src/core/geminiChat.ts | 8 +++++ .../core/src/services/chatRecordingService.ts | 31 +++++++++++++++++++ packages/core/src/telemetry/types.ts | 27 +++++++++++++++- 4 files changed, 70 insertions(+), 1 deletion(-) diff --git a/packages/core/src/core/client.ts b/packages/core/src/core/client.ts index 5d4e5a38df..a2a1cd8141 100644 --- a/packages/core/src/core/client.ts +++ b/packages/core/src/core/client.ts @@ -658,6 +658,11 @@ export class GeminiClient { if (adaptiveConfig) { modelConfigKey.thinkingBudget = adaptiveConfig.thinkingBudget; modelConfigKey.thinkingLevel = adaptiveConfig.thinkingLevel; + this.getChat().recordAdaptiveThinking({ + complexity: adaptiveConfig.complexity, + thinkingBudget: adaptiveConfig.thinkingBudget, + thinkingLevel: adaptiveConfig.thinkingLevel, + }); } } } diff --git a/packages/core/src/core/geminiChat.ts b/packages/core/src/core/geminiChat.ts index df98e3ebd7..aab1329f9d 100644 --- a/packages/core/src/core/geminiChat.ts +++ b/packages/core/src/core/geminiChat.ts @@ -260,6 +260,14 @@ export class GeminiChat { this.systemInstruction = sysInstr; } + recordAdaptiveThinking(info: { + complexity: number; + thinkingBudget?: number; + thinkingLevel?: string; + }) { + this.chatRecordingService.recordAdaptiveThinking(info); + } + /** * Sends a message to the model and returns the response in chunks. * diff --git a/packages/core/src/services/chatRecordingService.ts b/packages/core/src/services/chatRecordingService.ts index ebe66edf01..ea39f1ea2c 100644 --- a/packages/core/src/services/chatRecordingService.ts +++ b/packages/core/src/services/chatRecordingService.ts @@ -83,6 +83,11 @@ export type ConversationRecordExtra = thoughts?: Array; tokens?: TokensSummary | null; model?: string; + adaptiveThinking?: { + complexity: number; + thinkingBudget?: number; + thinkingLevel?: string; + }; }; /** @@ -130,6 +135,11 @@ export class ChatRecordingService { private projectHash: string; private queuedThoughts: Array = []; private queuedTokens: TokensSummary | null = null; + private queuedAdaptiveThinking?: { + complexity: number; + thinkingBudget?: number; + thinkingLevel?: string; + }; private config: Config; constructor(config: Config) { @@ -186,6 +196,7 @@ export class ChatRecordingService { // Clear any queued data since this is a fresh start this.queuedThoughts = []; this.queuedTokens = null; + this.queuedAdaptiveThinking = undefined; } catch (error) { // Handle disk full (ENOSPC) gracefully - disable recording but allow CLI to continue if ( @@ -230,6 +241,11 @@ export class ChatRecordingService { type: ConversationRecordExtra['type']; content: PartListUnion; displayContent?: PartListUnion; + adaptiveThinking?: { + complexity: number; + thinkingBudget?: number; + thinkingLevel?: string; + }; }): void { if (!this.conversationFile) return; @@ -247,9 +263,12 @@ export class ChatRecordingService { thoughts: this.queuedThoughts, tokens: this.queuedTokens, model: message.model, + adaptiveThinking: + message.adaptiveThinking || this.queuedAdaptiveThinking, }); this.queuedThoughts = []; this.queuedTokens = null; + this.queuedAdaptiveThinking = undefined; } else { // Or else just add it. conversation.messages.push(msg); @@ -261,6 +280,18 @@ export class ChatRecordingService { } } + /** + * Queues adaptive thinking info to be recorded with the next Gemini message. + */ + recordAdaptiveThinking(info: { + complexity: number; + thinkingBudget?: number; + thinkingLevel?: string; + }): void { + if (!this.conversationFile) return; + this.queuedAdaptiveThinking = info; + } + /** * Records a thought from the assistant's reasoning process. */ diff --git a/packages/core/src/telemetry/types.ts b/packages/core/src/telemetry/types.ts index 7a7399fd74..033b30d7cf 100644 --- a/packages/core/src/telemetry/types.ts +++ b/packages/core/src/telemetry/types.ts @@ -553,7 +553,7 @@ function toGenerateContentConfigAttributes( if (!config) { return {}; } - return { + const attributes: LogAttributes = { 'gen_ai.request.temperature': config.temperature, 'gen_ai.request.top_p': config.topP, 'gen_ai.request.top_k': config.topK, @@ -568,6 +568,20 @@ function toGenerateContentConfigAttributes( toSystemInstruction(config.systemInstruction), ), }; + + if (config.thinkingConfig) { + const thinkingConfig = config.thinkingConfig; + if (thinkingConfig.thinkingBudget !== undefined) { + attributes['gen_ai.request.thinking_budget'] = + thinkingConfig.thinkingBudget; + } + if (thinkingConfig.thinkingLevel !== undefined) { + attributes['gen_ai.request.thinking_level'] = + thinkingConfig.thinkingLevel; + } + } + + return attributes; } export class ApiResponseEvent implements BaseTelemetryEvent { @@ -632,6 +646,17 @@ export class ApiResponseEvent implements BaseTelemetryEvent { status_code: this.status_code, finish_reasons: this.finish_reasons, }; + + if (this.prompt.generate_content_config?.thinkingConfig) { + const thinkingConfig = this.prompt.generate_content_config.thinkingConfig; + if (thinkingConfig.thinkingBudget !== undefined) { + attributes['thinking_budget'] = thinkingConfig.thinkingBudget; + } + if (thinkingConfig.thinkingLevel !== undefined) { + attributes['thinking_level'] = thinkingConfig.thinkingLevel; + } + } + if (this.response_text) { attributes['response_text'] = this.response_text; }