diff --git a/packages/core/src/code_assist/telemetry.test.ts b/packages/core/src/code_assist/telemetry.test.ts index c838aeb943..c90040f22e 100644 --- a/packages/core/src/code_assist/telemetry.test.ts +++ b/packages/core/src/code_assist/telemetry.test.ts @@ -316,6 +316,14 @@ describe('telemetry', () => { prompt_id: 'p1', traceId: 'trace-1', }, + response: { + resultDisplay: { + diffStat: { + model_added_lines: 5, + model_removed_lines: 3, + }, + }, + }, outcome: ToolConfirmationOutcome.ProceedOnce, status: 'success', } as unknown as CompletedToolCall, @@ -327,6 +335,8 @@ describe('telemetry', () => { traceId: 'trace-1', status: ActionStatus.ACTION_STATUS_NO_ERROR, interaction: ConversationInteractionInteraction.ACCEPT_FILE, + acceptedLines: '5', + removedLines: '3', isAgentic: true, }); }); diff --git a/packages/core/src/code_assist/telemetry.ts b/packages/core/src/code_assist/telemetry.ts index ad02691d53..59ff179c50 100644 --- a/packages/core/src/code_assist/telemetry.ts +++ b/packages/core/src/code_assist/telemetry.ts @@ -22,6 +22,10 @@ import { EDIT_TOOL_NAMES } from '../tools/tool-names.js'; import { getErrorMessage } from '../utils/errors.js'; import type { CodeAssistServer } from './server.js'; import { ToolConfirmationOutcome } from '../tools/tools.js'; +import { + computeModelAddedAndRemovedLines, + getFileDiffFromResultDisplay, +} from '../utils/fileDiffUtils.js'; export async function recordConversationOffered( server: CodeAssistServer, @@ -110,6 +114,8 @@ function summarizeToolCalls( // Treat file edits as ACCEPT_FILE and everything else as unknown. let isEdit = false; + let acceptedLines = 0; + let removedLines = 0; // Iterate the tool calls and summarize them into a single conversation // interaction so that the ConversationOffered and ConversationInteraction @@ -136,7 +142,18 @@ function summarizeToolCalls( // Edits are ACCEPT_FILE, everything else is UNKNOWN. if (EDIT_TOOL_NAMES.has(toolCall.request.name)) { - isEdit ||= true; + isEdit = true; + + if (toolCall.status === 'success') { + const fileDiff = getFileDiffFromResultDisplay( + toolCall.response.resultDisplay, + ); + if (fileDiff?.diffStat) { + const lines = computeModelAddedAndRemovedLines(fileDiff.diffStat); + acceptedLines += lines.addedLines; + removedLines += lines.removedLines; + } + } } } } @@ -149,6 +166,8 @@ function summarizeToolCalls( isEdit ? ConversationInteractionInteraction.ACCEPT_FILE : ConversationInteractionInteraction.UNKNOWN, + isEdit ? String(acceptedLines) : undefined, + isEdit ? String(removedLines) : undefined, ) : undefined; } @@ -157,15 +176,18 @@ function createConversationInteraction( traceId: string, status: ActionStatus, interaction: ConversationInteractionInteraction, + acceptedLines?: string, + removedLines?: string, ): ConversationInteraction { return { traceId, status, interaction, + acceptedLines, + removedLines, isAgentic: true, }; } - function includesCode(resp: GenerateContentResponse): boolean { if (!resp.candidates) { return false; diff --git a/packages/core/src/code_assist/types.ts b/packages/core/src/code_assist/types.ts index 7845ceee89..0e2f353aa3 100644 --- a/packages/core/src/code_assist/types.ts +++ b/packages/core/src/code_assist/types.ts @@ -295,6 +295,7 @@ export interface ConversationInteraction { status?: ActionStatus; interaction?: ConversationInteractionInteraction; acceptedLines?: string; + removedLines?: string; language?: string; isAgentic?: boolean; } diff --git a/packages/core/src/utils/fileDiffUtils.ts b/packages/core/src/utils/fileDiffUtils.ts index bf9478627c..c0d3f64f37 100644 --- a/packages/core/src/utils/fileDiffUtils.ts +++ b/packages/core/src/utils/fileDiffUtils.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { FileDiff } from '../tools/tools.js'; +import type { DiffStat, FileDiff } from '../tools/tools.js'; import type { ToolCallRecord } from '../services/chatRecordingService.js'; /** @@ -23,17 +23,14 @@ export function getFileDiffFromResultDisplay( typeof resultDisplay.diffStat === 'object' && resultDisplay.diffStat !== null ) { - const diffStat = resultDisplay.diffStat as FileDiff['diffStat']; - if (diffStat) { + if (resultDisplay.diffStat) { return resultDisplay; } } return undefined; } -export function computeModelAddedAndRemovedLines( - stats: FileDiff['diffStat'] | undefined, -): { +export function computeModelAddedAndRemovedLines(stats: DiffStat | undefined): { addedLines: number; removedLines: number; } {