6
6
import type * as vscode from 'vscode' ;
7
7
import { DebugRecorder } from '../../extension/inlineEdits/node/debugRecorder' ;
8
8
import { INextEditProvider , NextEditProvider } from '../../extension/inlineEdits/node/nextEditProvider' ;
9
- import { LlmNESTelemetryBuilder } from '../../extension/inlineEdits/node/nextEditProviderTelemetry' ;
9
+ import { LlmNESTelemetryBuilder , NextEditProviderTelemetryBuilder , TelemetrySender } from '../../extension/inlineEdits/node/nextEditProviderTelemetry' ;
10
10
import { INextEditResult } from '../../extension/inlineEdits/node/nextEditResult' ;
11
11
import { ChatMLFetcherImpl } from '../../extension/prompt/node/chatMLFetcher' ;
12
12
import { XtabProvider } from '../../extension/xtab/node/xtabProvider' ;
@@ -115,13 +115,41 @@ export interface INESProviderOptions {
115
115
readonly logTarget ?: ILogTarget ;
116
116
}
117
117
118
- export function createNESProvider ( options : INESProviderOptions ) : INESProvider {
118
+ export interface INESResult {
119
+ readonly result ?: {
120
+ readonly newText : string ;
121
+ readonly range : {
122
+ readonly start : number ;
123
+ readonly endExclusive : number ;
124
+ } ;
125
+ } ;
126
+ }
127
+
128
+ export interface INESProvider < T extends INESResult = INESResult > {
129
+ getId ( ) : string ;
130
+ getNextEdit ( documentUri : vscode . Uri , cancellationToken : CancellationToken ) : Promise < T > ;
131
+ handleShown ( suggestion : T ) : void ;
132
+ handleAcceptance ( suggestion : T ) : void ;
133
+ handleRejection ( suggestion : T ) : void ;
134
+ handleIgnored ( suggestion : T , supersededByRequestUuid : T | undefined ) : void ;
135
+ dispose ( ) : void ;
136
+ }
137
+
138
+ export function createNESProvider ( options : INESProviderOptions ) : INESProvider < INESResult > {
119
139
const instantiationService = setupServices ( options ) ;
120
140
return instantiationService . createInstance ( NESProvider , options ) ;
121
141
}
122
142
123
- class NESProvider extends Disposable implements INESProvider {
143
+ interface NESResult extends INESResult {
144
+ docId : DocumentId ;
145
+ requestUuid : string ;
146
+ internalResult : INextEditResult ;
147
+ telemetryBuilder : NextEditProviderTelemetryBuilder ;
148
+ }
149
+
150
+ class NESProvider extends Disposable implements INESProvider < NESResult > {
124
151
private readonly _nextEditProvider : INextEditProvider < INextEditResult , LlmNESTelemetryBuilder > ;
152
+ private readonly _telemetrySender : TelemetrySender ;
125
153
private readonly _debugRecorder : DebugRecorder ;
126
154
127
155
constructor (
@@ -140,29 +168,49 @@ class NESProvider extends Disposable implements INESProvider {
140
168
this . _debugRecorder = this . _register ( new DebugRecorder ( this . _options . workspace ) ) ;
141
169
142
170
this . _nextEditProvider = instantiationService . createInstance ( NextEditProvider , this . _options . workspace , statelessNextEditProvider , historyContextProvider , xtabHistoryTracker , this . _debugRecorder ) ;
171
+ this . _telemetrySender = this . _register ( instantiationService . createInstance ( TelemetrySender ) ) ;
143
172
}
144
173
145
174
getId ( ) : string {
146
175
return this . _nextEditProvider . ID ;
147
176
}
148
177
149
- handleShown ( suggestion : INextEditResult ) : void {
150
- this . _nextEditProvider . handleShown ( suggestion ) ;
178
+ handleShown ( result : NESResult ) : void {
179
+ result . telemetryBuilder . setAsShown ( ) ;
180
+ this . _nextEditProvider . handleShown ( result . internalResult ) ;
151
181
}
152
182
153
- handleAcceptance ( docId : DocumentId , suggestion : INextEditResult ) : void {
154
- this . _nextEditProvider . handleAcceptance ( docId , suggestion ) ;
183
+ handleAcceptance ( result : NESResult ) : void {
184
+ result . telemetryBuilder . setAcceptance ( 'accepted' ) ;
185
+ result . telemetryBuilder . setStatus ( 'accepted' ) ;
186
+ this . _nextEditProvider . handleAcceptance ( result . docId , result . internalResult ) ;
187
+ this . handleEndOfLifetime ( result ) ;
155
188
}
156
189
157
- handleRejection ( docId : DocumentId , suggestion : INextEditResult ) : void {
158
- this . _nextEditProvider . handleRejection ( docId , suggestion ) ;
190
+ handleRejection ( result : NESResult ) : void {
191
+ result . telemetryBuilder . setAcceptance ( 'rejected' ) ;
192
+ result . telemetryBuilder . setStatus ( 'rejected' ) ;
193
+ this . _nextEditProvider . handleRejection ( result . docId , result . internalResult ) ;
194
+ this . handleEndOfLifetime ( result ) ;
159
195
}
160
196
161
- handleIgnored ( docId : DocumentId , suggestion : INextEditResult , supersededByRequestUuid : INextEditResult | undefined ) : void {
162
- this . _nextEditProvider . handleIgnored ( docId , suggestion , supersededByRequestUuid ) ;
197
+ handleIgnored ( result : NESResult , supersededByRequestUuid : NESResult | undefined ) : void {
198
+ if ( supersededByRequestUuid ) {
199
+ result . telemetryBuilder . setSupersededBy ( supersededByRequestUuid . requestUuid ) ;
200
+ }
201
+ this . _nextEditProvider . handleIgnored ( result . docId , result . internalResult , supersededByRequestUuid ?. internalResult ) ;
202
+ this . handleEndOfLifetime ( result ) ;
163
203
}
164
204
165
- async getNextEdit ( documentUri : vscode . Uri , cancellationToken : CancellationToken ) : Promise < INextEditResult > {
205
+ private handleEndOfLifetime ( result : NESResult ) : void {
206
+ try {
207
+ this . _telemetrySender . sendTelemetryForBuilder ( result . telemetryBuilder ) ;
208
+ } finally {
209
+ result . telemetryBuilder . dispose ( ) ;
210
+ }
211
+ }
212
+
213
+ async getNextEdit ( documentUri : vscode . Uri , cancellationToken : CancellationToken ) : Promise < NESResult > {
166
214
const docId = DocumentId . create ( documentUri . toString ( ) ) ;
167
215
168
216
// Create minimal required context objects
@@ -183,30 +231,41 @@ class NESProvider extends Disposable implements INESProvider {
183
231
}
184
232
185
233
// Create telemetry builder - we'll need to pass null/undefined for services we don't have
186
- const telemetryBuilder = new LlmNESTelemetryBuilder (
187
- new NullGitExtensionService ( ) , // IGitExtensionService
234
+ const telemetryBuilder = new NextEditProviderTelemetryBuilder (
235
+ new NullGitExtensionService ( ) ,
188
236
undefined , // INotebookService
189
- this . _workspaceService , // IWorkspaceService
190
- this . _nextEditProvider . ID , // providerId
191
- document , // doc
192
- this . _debugRecorder , // debugRecorder
193
- undefined // requestBookmark
237
+ this . _workspaceService ,
238
+ this . _nextEditProvider . ID ,
239
+ document ,
240
+ this . _debugRecorder ,
241
+ logContext . recordingBookmark
194
242
) ;
195
-
196
- return await this . _nextEditProvider . getNextEdit ( docId , context , logContext , cancellationToken , telemetryBuilder ) ;
243
+ telemetryBuilder . setOpportunityId ( context . requestUuid ) ;
244
+
245
+ try {
246
+ const internalResult = await this . _nextEditProvider . getNextEdit ( docId , context , logContext , cancellationToken , telemetryBuilder . nesBuilder ) ;
247
+ const result : NESResult = {
248
+ result : internalResult . result ? {
249
+ newText : internalResult . result . edit . newText ,
250
+ range : internalResult . result . edit . replaceRange ,
251
+ } : undefined ,
252
+ docId,
253
+ requestUuid : context . requestUuid ,
254
+ internalResult,
255
+ telemetryBuilder,
256
+ } ;
257
+ return result ;
258
+ } catch ( e ) {
259
+ try {
260
+ this . _telemetrySender . sendTelemetryForBuilder ( telemetryBuilder ) ;
261
+ } finally {
262
+ telemetryBuilder . dispose ( ) ;
263
+ }
264
+ throw e ;
265
+ }
197
266
}
198
267
}
199
268
200
- export interface INESProvider {
201
- getId ( ) : string ;
202
- getNextEdit ( documentUri : vscode . Uri , cancellationToken : CancellationToken ) : Promise < INextEditResult > ;
203
- handleShown ( suggestion : INextEditResult ) : void ;
204
- handleAcceptance ( docId : DocumentId , suggestion : INextEditResult ) : void ;
205
- handleRejection ( docId : DocumentId , suggestion : INextEditResult ) : void ;
206
- handleIgnored ( docId : DocumentId , suggestion : INextEditResult , supersededByRequestUuid : INextEditResult | undefined ) : void ;
207
- dispose ( ) : void ;
208
- }
209
-
210
269
function setupServices ( options : INESProviderOptions ) {
211
270
const { fetcher, copilotTokenManager, telemetrySender, logTarget } = options ;
212
271
const builder = new InstantiationServiceBuilder ( ) ;
0 commit comments