diff --git a/docs/telemetry-events.md b/docs/telemetry-events.md index 6272c9f934931..ff5ef7cd92aaa 100644 --- a/docs/telemetry-events.md +++ b/docs/telemetry-events.md @@ -146,6 +146,7 @@ ```typescript { + 'feature': string, 'id': string, 'model.id': string, 'model.provider.id': 'anthropic' | 'azure' | 'deepseek' | 'gemini' | 'github' | 'gitkraken' | 'huggingface' | 'mistral' | 'ollama' | 'openai' | 'openaicompatible' | 'openrouter' | 'vscode' | 'xai', diff --git a/src/commands/aiFeedback.ts b/src/commands/aiFeedback.ts index 76aa20d728e84..8e88489cb10ad 100644 --- a/src/commands/aiFeedback.ts +++ b/src/commands/aiFeedback.ts @@ -121,6 +121,7 @@ function sendFeedbackEvent( ): void { const eventData: AIFeedbackEvent = { type: context.type, + feature: context.feature, sentiment: sentiment, 'unhelpful.reasons': unhelpful?.reasons?.length ? unhelpful.reasons.join(',') : undefined, 'unhelpful.custom': unhelpful?.custom?.trim() ?? undefined, diff --git a/src/constants.telemetry.ts b/src/constants.telemetry.ts index 7ab3fed1318e2..a906ed0de1c0d 100644 --- a/src/constants.telemetry.ts +++ b/src/constants.telemetry.ts @@ -419,6 +419,7 @@ export type AIFeedbackUnhelpfulReasons = export interface AIFeedbackEvent extends AIEventDataBase { /** The AI feature that feedback was submitted for */ type: AIActionType; + feature: string; sentiment: 'helpful' | 'unhelpful'; /** Unhelpful reasons selected (if any) - comma-separated list of AIFeedbackUnhelpfulReasons values */ 'unhelpful.reasons'?: string; diff --git a/src/plus/ai/aiProviderService.ts b/src/plus/ai/aiProviderService.ts index a86ba67d06c9b..064569bb5cdb4 100644 --- a/src/plus/ai/aiProviderService.ts +++ b/src/plus/ai/aiProviderService.ts @@ -120,6 +120,7 @@ function dedent(template: string): string { export interface AIResult { readonly id: string; readonly type: AIActionType; + readonly feature: string; readonly content: string; readonly model: AIModel; readonly usage?: { @@ -647,7 +648,12 @@ export class AIProviderService implements Disposable { return result === 'cancelled' ? result : result != null - ? { ...result, type: 'explain-changes', parsed: parseSummarizeResult(result.content) } + ? { + ...result, + type: 'explain-changes', + feature: `explain-${type}`, + parsed: parseSummarizeResult(result.content), + } : undefined; } @@ -703,7 +709,12 @@ export class AIProviderService implements Disposable { return result === 'cancelled' ? result : result != null - ? { ...result, type: 'generate-commitMessage', parsed: parseSummarizeResult(result.content) } + ? { + ...result, + type: 'generate-commitMessage', + feature: 'generate-commitMessage', + parsed: parseSummarizeResult(result.content), + } : undefined; } @@ -767,7 +778,12 @@ export class AIProviderService implements Disposable { return result === 'cancelled' ? result : result != null - ? { ...result, type: 'generate-create-pullRequest', parsed: parseSummarizeResult(result.content) } + ? { + ...result, + type: 'generate-create-pullRequest', + feature: 'generate-create-pullRequest', + parsed: parseSummarizeResult(result.content), + } : undefined; } @@ -839,6 +855,9 @@ export class AIProviderService implements Disposable { ? { ...result, type: options?.codeSuggestion ? 'generate-create-codeSuggestion' : 'generate-create-cloudPatch', + feature: options?.codeSuggestion + ? 'generate-create-codeSuggestion' + : 'generate-create-cloudPatch', parsed: parseSummarizeResult(result.content), } : undefined; @@ -896,7 +915,12 @@ export class AIProviderService implements Disposable { return result === 'cancelled' ? result : result != null - ? { ...result, type: 'generate-stashMessage', parsed: parseSummarizeResult(result.content) } + ? { + ...result, + type: 'generate-stashMessage', + feature: 'generate-stashMessage', + parsed: parseSummarizeResult(result.content), + } : undefined; } @@ -943,7 +967,11 @@ export class AIProviderService implements Disposable { }), options, ); - return result === 'cancelled' ? result : result != null ? { ...result, type: 'generate-changelog' } : undefined; + return result === 'cancelled' + ? result + : result != null + ? { ...result, type: 'generate-changelog', feature: 'generate-changelog' } + : undefined; } async generateSearchQuery( @@ -990,7 +1018,7 @@ export class AIProviderService implements Disposable { return result === 'cancelled' ? result : result != null - ? { ...result, type: 'generate-searchQuery' } + ? { ...result, type: 'generate-searchQuery', feature: 'generate-searchQuery' } : undefined; } @@ -1064,6 +1092,8 @@ export class AIProviderService implements Disposable { return { ...rq, ...result, + type: 'generate-rebase', + feature: options?.generateCommits ? 'generate-commits' : 'generate-rebase', }; } diff --git a/src/plus/ai/utils/-webview/ai.utils.ts b/src/plus/ai/utils/-webview/ai.utils.ts index 18ce3f1696509..339b7538410df 100644 --- a/src/plus/ai/utils/-webview/ai.utils.ts +++ b/src/plus/ai/utils/-webview/ai.utils.ts @@ -261,6 +261,7 @@ export function getAIResultContext(result: AIResult): AIResultContext { return { id: result.id, type: result.type, + feature: result.feature, model: result.model, usage: result.usage != null