11import type { TextEditor , Uri } from 'vscode' ;
22import { window } from 'vscode' ;
33import { Schemes } from '../constants' ;
4+ import type { AIFeedbackEvent , Source } from '../constants.telemetry' ;
45import type { Container } from '../container' ;
56import type { MarkdownContentMetadata } from '../documents/markdown' ;
67import { decodeGitLensRevisionUriAuthority } from '../git/gitUri.authority' ;
7- import type { AIFeedbackContext } from '../plus/ai/aiFeedbackService' ;
88import { command } from '../system/-webview/command' ;
99import { Logger } from '../system/logger' ;
1010import { ActiveEditorCommand } from './commandBase' ;
1111import { getCommandUri } from './commandBase.utils' ;
1212
13+ export interface AIFeedbackContext {
14+ feature : AIFeedbackEvent [ 'feature' ] ;
15+ model : {
16+ id : string ;
17+ providerId : string ;
18+ providerName : string ;
19+ } ;
20+ usage ?: {
21+ promptTokens ?: number ;
22+ completionTokens ?: number ;
23+ totalTokens ?: number ;
24+ limits ?: {
25+ used : number ;
26+ limit : number ;
27+ resetsOn : Date ;
28+ } ;
29+ } ;
30+ aiRequestId : string | undefined ;
31+ outputLength : number ;
32+ }
33+
1334export interface AIFeedbackCommandArgs {
1435 context : AIFeedbackContext ;
1536}
1637
38+ function sendFeedbackEvent (
39+ container : Container ,
40+ context : AIFeedbackContext ,
41+ rating : 'positive' | 'negative' ,
42+ feedback : {
43+ presetReasons ?: string [ ] ;
44+ writeInFeedback ?: string ;
45+ } ,
46+ source : Source ,
47+ ) : void {
48+ const hasPresetReasons = feedback . presetReasons && feedback . presetReasons . length > 0 ;
49+ const writeInFeedback = feedback . writeInFeedback ?. trim ( ) ?? undefined ;
50+
51+ let feedbackType : 'preset' | 'writeIn' | 'both' ;
52+ if ( hasPresetReasons && writeInFeedback ?. length ) {
53+ feedbackType = 'both' ;
54+ } else if ( hasPresetReasons ) {
55+ feedbackType = 'preset' ;
56+ } else {
57+ feedbackType = 'writeIn' ;
58+ }
59+
60+ const eventData : AIFeedbackEvent = {
61+ feature : context . feature ,
62+ rating : rating ,
63+ feedbackType : feedbackType ,
64+ presetReason : hasPresetReasons ? feedback . presetReasons ! . join ( ', ' ) : undefined ,
65+ 'writeInFeedback.length' : writeInFeedback ?. length ?? undefined ,
66+ 'writeInFeedback.text' : writeInFeedback ?. length ? writeInFeedback : undefined ,
67+ 'model.id' : context . model . id ,
68+ 'model.provider.id' : context . model . providerId as any ,
69+ 'model.provider.name' : context . model . providerName ,
70+ 'usage.promptTokens' : context . usage ?. promptTokens ,
71+ 'usage.completionTokens' : context . usage ?. completionTokens ,
72+ 'usage.totalTokens' : context . usage ?. totalTokens ,
73+ 'usage.limits.used' : context . usage ?. limits ?. used ,
74+ 'usage.limits.limit' : context . usage ?. limits ?. limit ,
75+ 'usage.limits.resetsOn' : context . usage ?. limits ?. resetsOn ?. toISOString ( ) ,
76+ 'ai.request.id' : context . aiRequestId ,
77+ 'output.length' : context . outputLength ,
78+ } ;
79+
80+ container . telemetry . sendEvent ( 'ai/feedback' , eventData , source ) ;
81+ }
82+
1783@command ( )
1884export class AIFeedbackPositiveCommand extends ActiveEditorCommand {
1985 constructor ( private readonly container : Container ) {
@@ -30,7 +96,8 @@ export class AIFeedbackPositiveCommand extends ActiveEditorCommand {
3096
3197 try {
3298 // For positive feedback, just send the event immediately without showing any form
33- this . container . aiFeedback . sendFeedbackEvent (
99+ sendFeedbackEvent (
100+ this . container ,
34101 context ,
35102 'positive' ,
36103 {
@@ -142,7 +209,8 @@ async function showDetailedFeedbackForm(container: Container, context: AIFeedbac
142209 } ) ;
143210
144211 // Always send feedback submission telemetry for negative feedback
145- container . aiFeedback . sendFeedbackEvent (
212+ sendFeedbackEvent (
213+ container ,
146214 context ,
147215 'negative' ,
148216 {
0 commit comments