@vscode/chat-lib 0.2.1-32 → 0.2.1-34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.d.ts.map +1 -1
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js +3 -1
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js.map +1 -1
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts +16 -0
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts.map +1 -1
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js +57 -2
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.d.ts +2 -2
- package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.d.ts.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js +15 -13
- package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.d.ts +3 -1
- package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.d.ts.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js +4 -3
- package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts +5 -28
- package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabProvider.js +197 -192
- package/dist/src/_internal/extension/xtab/node/xtabProvider.js.map +1 -1
- package/dist/src/_internal/platform/configuration/common/configurationService.d.ts +14 -2
- package/dist/src/_internal/platform/configuration/common/configurationService.d.ts.map +1 -1
- package/dist/src/_internal/platform/configuration/common/configurationService.js +8 -4
- package/dist/src/_internal/platform/configuration/common/configurationService.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js +4 -0
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/messagesApi.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/messagesApi.js +4 -2
- package/dist/src/_internal/platform/endpoint/node/messagesApi.js.map +1 -1
- package/dist/src/_internal/platform/git/common/gitService.d.ts +2 -1
- package/dist/src/_internal/platform/git/common/gitService.d.ts.map +1 -1
- package/dist/src/_internal/platform/git/common/gitService.js.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts +4 -0
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js +3 -0
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts +8 -2
- package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js +10 -0
- package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js.map +1 -1
- package/dist/src/_internal/platform/networking/common/anthropic.d.ts +8 -8
- package/dist/src/_internal/platform/networking/common/anthropic.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/common/anthropic.js +33 -20
- package/dist/src/_internal/platform/networking/common/anthropic.js.map +1 -1
- package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts +8 -4
- package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts.map +1 -1
- package/dist/src/_internal/util/common/test/shims/chatTypes.js +13 -7
- package/dist/src/_internal/util/common/test/shims/chatTypes.js.map +1 -1
- package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js +3 -3
- package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js.map +1 -1
- package/dist/src/_internal/vscodeTypes.d.ts +1 -1
- package/dist/src/_internal/vscodeTypes.d.ts.map +1 -1
- package/dist/src/_internal/vscodeTypes.js +3 -3
- package/dist/src/_internal/vscodeTypes.js.map +1 -1
- package/dist/src/package.json +133 -20
- package/package.json +2 -2
|
@@ -133,47 +133,7 @@ let XtabProvider = class XtabProvider {
|
|
|
133
133
|
handleRejection() {
|
|
134
134
|
this.userInteractionMonitor.handleRejection();
|
|
135
135
|
}
|
|
136
|
-
provideNextEdit(request, pushEdit, tracer, logContext, cancellationToken) {
|
|
137
|
-
const filteringPushEdit = (result) => {
|
|
138
|
-
if (result.isError()) {
|
|
139
|
-
pushEdit(result);
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const { edit } = result.val;
|
|
143
|
-
const filteredEdits = this.filterEdit(request.getActiveDocument(), [edit]);
|
|
144
|
-
if (filteredEdits.length === 0) { // do not invoke pushEdit
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
pushEdit(result);
|
|
148
|
-
};
|
|
149
|
-
return this._provideNextEdit(request, filteringPushEdit, tracer, logContext, cancellationToken);
|
|
150
|
-
}
|
|
151
|
-
filterEdit(activeDoc, edits) {
|
|
152
|
-
const filters = [
|
|
153
|
-
(edits) => importFiltering_1.IgnoreImportChangesAspect.filterEdit(activeDoc, edits),
|
|
154
|
-
(edits) => statelessNextEditProviders_1.IgnoreEmptyLineAndLeadingTrailingWhitespaceChanges.filterEdit(activeDoc, edits),
|
|
155
|
-
];
|
|
156
|
-
if (!this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.InlineEditsAllowWhitespaceOnlyChanges, this.expService)) {
|
|
157
|
-
filters.push((edits) => statelessNextEditProviders_1.IgnoreWhitespaceOnlyChanges.filterEdit(activeDoc, edits));
|
|
158
|
-
}
|
|
159
|
-
const undoInsertionFiltering = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsUndoInsertionFiltering, this.expService);
|
|
160
|
-
if (undoInsertionFiltering !== undefined) {
|
|
161
|
-
let filter;
|
|
162
|
-
switch (undoInsertionFiltering) {
|
|
163
|
-
case 'v1':
|
|
164
|
-
filter = statelessNextEditProviders_1.editWouldDeleteWhatWasJustInserted;
|
|
165
|
-
break;
|
|
166
|
-
case 'v2':
|
|
167
|
-
filter = statelessNextEditProviders_1.editWouldDeleteWhatWasJustInserted2;
|
|
168
|
-
break;
|
|
169
|
-
default:
|
|
170
|
-
(0, assert_1.assertNever)(undoInsertionFiltering);
|
|
171
|
-
}
|
|
172
|
-
filters.push((edits) => filter(activeDoc, new lineEdit_1.LineEdit(edits)) ? [] : edits);
|
|
173
|
-
}
|
|
174
|
-
return filters.reduce((acc, filter) => filter(acc), edits);
|
|
175
|
-
}
|
|
176
|
-
async _provideNextEdit(request, pushEdit, tracer, logContext, cancellationToken) {
|
|
136
|
+
async provideNextEdit(request, pushEdit, tracer, logContext, cancellationToken) {
|
|
177
137
|
const telemetry = new statelessNextEditProvider_1.StatelessNextEditTelemetryBuilder(request);
|
|
178
138
|
logContext.setProviderStartTime();
|
|
179
139
|
try {
|
|
@@ -181,7 +141,31 @@ let XtabProvider = class XtabProvider {
|
|
|
181
141
|
return statelessNextEditProvider_1.StatelessNextEditResult.noEdit(new statelessNextEditProvider_1.NoNextEditReason.ActiveDocumentHasNoEdits(), telemetry);
|
|
182
142
|
}
|
|
183
143
|
const delaySession = this.userInteractionMonitor.createDelaySession(request.providerRequestStartDateTime);
|
|
184
|
-
const
|
|
144
|
+
const iterator = this.doGetNextEdit(request, delaySession, tracer, logContext, cancellationToken, telemetry, RetryState.NotRetrying.INSTANCE);
|
|
145
|
+
let res = await iterator.next(); // for-async-await loop doesn't work because we need to access the final return value
|
|
146
|
+
let nextEditResult;
|
|
147
|
+
if (res.done) {
|
|
148
|
+
// stream already ended, so we can just return the final reason
|
|
149
|
+
nextEditResult = result_1.Result.error(res.value);
|
|
150
|
+
pushEdit(nextEditResult);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// stream is not done yet, so we push the first edit and then continue streaming in the background
|
|
154
|
+
nextEditResult = result_1.Result.ok(undefined);
|
|
155
|
+
(async () => {
|
|
156
|
+
let nEdits = 0;
|
|
157
|
+
while (!res.done) {
|
|
158
|
+
nEdits++;
|
|
159
|
+
pushEdit(result_1.Result.ok(res.value));
|
|
160
|
+
res = await iterator.next();
|
|
161
|
+
}
|
|
162
|
+
pushEdit(result_1.Result.error(res.value));
|
|
163
|
+
})().catch((err) => {
|
|
164
|
+
const error = errors.fromUnknown(err);
|
|
165
|
+
logContext.addLog(`Error while streaming further edits: ${errors.fromUnknown(err)}`);
|
|
166
|
+
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(error)));
|
|
167
|
+
});
|
|
168
|
+
}
|
|
185
169
|
if (nextEditResult.isError() && nextEditResult.err instanceof statelessNextEditProvider_1.NoNextEditReason.GotCancelled) {
|
|
186
170
|
logContext.setIsSkipped();
|
|
187
171
|
}
|
|
@@ -194,14 +178,14 @@ let XtabProvider = class XtabProvider {
|
|
|
194
178
|
logContext.setProviderEndTime();
|
|
195
179
|
}
|
|
196
180
|
}
|
|
197
|
-
|
|
198
|
-
return this.doGetNextEditWithSelection(request, (0, nearbyCursorInlineEditProvider_1.getOrDeduceSelectionFromLastEdit)(request.getActiveDocument()),
|
|
181
|
+
doGetNextEdit(request, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, retryState) {
|
|
182
|
+
return this.doGetNextEditWithSelection(request, (0, nearbyCursorInlineEditProvider_1.getOrDeduceSelectionFromLastEdit)(request.getActiveDocument()), delaySession, tracer, logContext, cancellationToken, telemetryBuilder, retryState);
|
|
199
183
|
}
|
|
200
|
-
async doGetNextEditWithSelection(request, selection,
|
|
184
|
+
async *doGetNextEditWithSelection(request, selection, delaySession, parentTracer, logContext, cancellationToken, telemetryBuilder, retryState) {
|
|
201
185
|
const tracer = parentTracer.sub(['XtabProvider', 'doGetNextEditWithSelection']);
|
|
202
186
|
const activeDocument = request.getActiveDocument();
|
|
203
187
|
if (selection === null) {
|
|
204
|
-
return
|
|
188
|
+
return new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('NoSelection'));
|
|
205
189
|
}
|
|
206
190
|
const promptOptions = this.determineModelConfiguration(activeDocument);
|
|
207
191
|
const endpoint = this.getEndpoint(promptOptions.modelName);
|
|
@@ -221,14 +205,14 @@ let XtabProvider = class XtabProvider {
|
|
|
221
205
|
}
|
|
222
206
|
telemetryBuilder.setIsCursorAtLineEnd(isCursorAtEndOfLine);
|
|
223
207
|
const areaAroundEditWindowLinesRange = this.computeAreaAroundEditWindowLinesRange(currentDocument);
|
|
224
|
-
const editWindowLinesRange = this.computeEditWindowLinesRange(currentDocument, request,
|
|
208
|
+
const editWindowLinesRange = this.computeEditWindowLinesRange(currentDocument, request, tracer, telemetryBuilder);
|
|
225
209
|
const cursorOriginalLinesOffset = Math.max(0, currentDocument.cursorLineOffset - editWindowLinesRange.start);
|
|
226
210
|
const editWindowLastLineLength = currentDocument.transformer.getLineLength(editWindowLinesRange.endExclusive);
|
|
227
211
|
const editWindow = currentDocument.transformer.getOffsetRange(new range_1.Range(editWindowLinesRange.start + 1, 1, editWindowLinesRange.endExclusive, editWindowLastLineLength + 1));
|
|
228
212
|
const editWindowLines = currentDocument.lines.slice(editWindowLinesRange.start, editWindowLinesRange.endExclusive);
|
|
229
213
|
const editWindowTokenLimit = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabEditWindowMaxTokens, this.expService);
|
|
230
214
|
if (editWindowTokenLimit !== undefined && (0, promptCrafting_1.countTokensForLines)(editWindowLines, XtabProvider_1.computeTokens) > editWindowTokenLimit) {
|
|
231
|
-
return
|
|
215
|
+
return new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('editWindow');
|
|
232
216
|
}
|
|
233
217
|
// Expected: editWindow.substring(activeDocument.documentAfterEdits.value) === editWindowLines.join('\n')
|
|
234
218
|
const doesIncludeCursorTag = editWindowLines.some(line => line.includes(tags_1.PromptTags.CURSOR));
|
|
@@ -240,7 +224,7 @@ let XtabProvider = class XtabProvider {
|
|
|
240
224
|
}
|
|
241
225
|
});
|
|
242
226
|
if (taggedCurrentFileContentResult.isError()) {
|
|
243
|
-
return
|
|
227
|
+
return new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('currentFile');
|
|
244
228
|
}
|
|
245
229
|
const { clippedTaggedCurrentDoc, areaAroundCodeToEdit } = taggedCurrentFileContentResult.val;
|
|
246
230
|
telemetryBuilder.setNLinesOfCurrentFileInPrompt(clippedTaggedCurrentDoc.lines.length);
|
|
@@ -254,7 +238,7 @@ let XtabProvider = class XtabProvider {
|
|
|
254
238
|
}
|
|
255
239
|
const langCtx = await this.getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, tracer, logContext, cancellationToken);
|
|
256
240
|
if (cancellationToken.isCancellationRequested) {
|
|
257
|
-
return
|
|
241
|
+
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterLanguageContextAwait');
|
|
258
242
|
}
|
|
259
243
|
const lintErrors = promptOptions.lintOptions ? new lintErrors_1.LintErrors(promptOptions.lintOptions, activeDocument.id, currentDocument, this.langDiagService) : undefined;
|
|
260
244
|
const promptPieces = new promptCrafting_1.PromptPieces(currentDocument, editWindowLinesRange, areaAroundEditWindowLinesRange, activeDocument, request.xtabEditHistory, clippedTaggedCurrentDoc.lines, areaAroundCodeToEdit, langCtx, aggressivenessLevel, lintErrors, XtabProvider_1.computeTokens, promptOptions);
|
|
@@ -270,20 +254,19 @@ let XtabProvider = class XtabProvider {
|
|
|
270
254
|
const HARD_CHAR_LIMIT = 30000 * 4; // 30K tokens, assuming 4 chars per token -- we use approximation here because counting tokens exactly is time-consuming
|
|
271
255
|
const promptCharCount = (0, xtabUtils_1.charCount)(messages);
|
|
272
256
|
if (promptCharCount > HARD_CHAR_LIMIT) {
|
|
273
|
-
return
|
|
257
|
+
return new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('final');
|
|
274
258
|
}
|
|
275
259
|
await this.debounce(delaySession, retryState, tracer, telemetryBuilder);
|
|
276
260
|
if (cancellationToken.isCancellationRequested) {
|
|
277
|
-
return
|
|
261
|
+
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterDebounce');
|
|
278
262
|
}
|
|
279
263
|
request.fetchIssued = true;
|
|
280
264
|
const cursorLineOffset = cursorPosition.column;
|
|
281
|
-
this.
|
|
265
|
+
return yield* this.streamEditsWithFiltering(request, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, editWindowLinesRange, promptPieces, prediction, {
|
|
282
266
|
shouldRemoveCursorTagFromResponse,
|
|
283
267
|
responseFormat,
|
|
284
268
|
retryState,
|
|
285
269
|
}, delaySession, tracer, telemetryBuilder, logContext, cancellationToken);
|
|
286
|
-
return result_1.Result.ok(undefined);
|
|
287
270
|
}
|
|
288
271
|
getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, tracer, logContext, cancellationToken) {
|
|
289
272
|
const recordingEnabled = this.configService.getConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsLogContextRecorderEnabled);
|
|
@@ -366,7 +349,34 @@ let XtabProvider = class XtabProvider {
|
|
|
366
349
|
return undefined;
|
|
367
350
|
}
|
|
368
351
|
}
|
|
369
|
-
async
|
|
352
|
+
async *streamEditsWithFiltering(request, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, // cursor offset within the line it's in; 1-based
|
|
353
|
+
editWindowLineRange, promptPieces, prediction, opts, delaySession, parentTracer, telemetryBuilder, logContext, cancellationToken) {
|
|
354
|
+
const tracer = parentTracer.sub('streamEditsWithFiltering');
|
|
355
|
+
const iterator = this.streamEdits(request, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, editWindowLineRange, promptPieces, prediction, opts, delaySession, tracer, telemetryBuilder, logContext, cancellationToken);
|
|
356
|
+
let nEdits = 0;
|
|
357
|
+
let r = await iterator.next();
|
|
358
|
+
while (!r.done) {
|
|
359
|
+
const edit = r.value.edit;
|
|
360
|
+
const filteredEdits = this.filterEdit(request.getActiveDocument(), [edit]);
|
|
361
|
+
const isFilteredOut = filteredEdits.length === 0;
|
|
362
|
+
if (isFilteredOut) {
|
|
363
|
+
tracer.trace(`Filtered out an edit: ${edit.toString()}`);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
tracer.trace(`Yielding an edit: ${edit.toString()}`);
|
|
367
|
+
yield r.value;
|
|
368
|
+
nEdits++;
|
|
369
|
+
}
|
|
370
|
+
r = await iterator.next();
|
|
371
|
+
}
|
|
372
|
+
if (nEdits === 0 &&
|
|
373
|
+
r.value instanceof statelessNextEditProvider_1.NoNextEditReason.NoSuggestions // only retry if there was no error, cancellation, etc.
|
|
374
|
+
) {
|
|
375
|
+
return yield* this.doGetNextEditsWithCursorJump(request, editWindow, promptPieces, delaySession, parentTracer, logContext, cancellationToken, telemetryBuilder, opts.retryState);
|
|
376
|
+
}
|
|
377
|
+
return r.value;
|
|
378
|
+
}
|
|
379
|
+
async *streamEdits(request, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, // cursor offset within the line it's in; 1-based
|
|
370
380
|
editWindowLineRange, promptPieces, prediction, opts, delaySession, parentTracer, telemetryBuilder, logContext, cancellationToken) {
|
|
371
381
|
const tracer = parentTracer.sub('streamEdits');
|
|
372
382
|
const useFetcher = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.NextEditSuggestionsFetcher, this.expService) || undefined;
|
|
@@ -416,10 +426,9 @@ let XtabProvider = class XtabProvider {
|
|
|
416
426
|
!this.forceUseDefaultModel // if we haven't already forced using the default model; otherwise, this could cause an infinite loop
|
|
417
427
|
) {
|
|
418
428
|
this.forceUseDefaultModel = true;
|
|
419
|
-
return this.doGetNextEdit(request,
|
|
429
|
+
return yield* this.doGetNextEdit(request, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState); // use the same retry state
|
|
420
430
|
}
|
|
421
|
-
|
|
422
|
-
return;
|
|
431
|
+
return XtabProvider_1.mapChatFetcherErrorToNoNextEditReason(fetchRes);
|
|
423
432
|
}
|
|
424
433
|
fetchResultPromise
|
|
425
434
|
.then((response) => {
|
|
@@ -431,8 +440,6 @@ let XtabProvider = class XtabProvider {
|
|
|
431
440
|
// in principle this shouldn't happen because ChatMLFetcher's fetchOne should not throw
|
|
432
441
|
logContext.setError(errors.fromUnknown(err));
|
|
433
442
|
logContext.addLog(`ChatMLFetcher fetch call threw -- this's UNEXPECTED!`);
|
|
434
|
-
// Properly handle the error by pushing it as a result
|
|
435
|
-
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(err))));
|
|
436
443
|
}).finally(() => {
|
|
437
444
|
logContext.setFetchEndTime();
|
|
438
445
|
if (!firstTokenReceived.isSettled) {
|
|
@@ -460,32 +467,28 @@ let XtabProvider = class XtabProvider {
|
|
|
460
467
|
cleanedLinesStream = linesStream;
|
|
461
468
|
}
|
|
462
469
|
else if (opts.responseFormat === xtabPromptOptions.ResponseFormat.CustomDiffPatch) {
|
|
463
|
-
return xtabCustomDiffPatchResponseHandler_1.XtabCustomDiffPatchResponseHandler.handleResponse(
|
|
470
|
+
return yield* xtabCustomDiffPatchResponseHandler_1.XtabCustomDiffPatchResponseHandler.handleResponse(linesStream, request.documentBeforeEdits, editWindow);
|
|
464
471
|
}
|
|
465
472
|
else if (opts.responseFormat === xtabPromptOptions.ResponseFormat.UnifiedWithXml) {
|
|
466
473
|
const linesIter = linesStream[Symbol.asyncIterator]();
|
|
467
474
|
const firstLine = await linesIter.next();
|
|
468
475
|
if (chatResponseFailure !== undefined) { // handle fetch failure
|
|
469
|
-
|
|
470
|
-
return;
|
|
476
|
+
return new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(chatResponseFailure));
|
|
471
477
|
}
|
|
472
478
|
if (firstLine.done) { // no lines in response -- unexpected case but take as no suggestions
|
|
473
|
-
|
|
474
|
-
return;
|
|
479
|
+
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
475
480
|
}
|
|
476
481
|
const trimmedLines = firstLine.value.trim();
|
|
477
482
|
if (trimmedLines === tags_1.ResponseTags.NO_CHANGE.start) {
|
|
478
|
-
|
|
479
|
-
return;
|
|
483
|
+
return yield* this.doGetNextEditsWithCursorJump(request, editWindow, promptPieces, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState);
|
|
480
484
|
}
|
|
481
485
|
if (trimmedLines === tags_1.ResponseTags.INSERT.start) {
|
|
482
486
|
const lineWithCursorContinued = await linesIter.next();
|
|
483
487
|
if (lineWithCursorContinued.done || lineWithCursorContinued.value.includes(tags_1.ResponseTags.INSERT.end)) {
|
|
484
|
-
|
|
485
|
-
return;
|
|
488
|
+
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
486
489
|
}
|
|
487
490
|
const edit = new lineEdit_1.LineReplacement(new lineRange_1.LineRange(editWindowLineRange.start + cursorOriginalLinesOffset + 1 /* 0-based to 1-based */, editWindowLineRange.start + cursorOriginalLinesOffset + 2), [editWindowLines[cursorOriginalLinesOffset].slice(0, cursorLineOffset - 1) + lineWithCursorContinued.value + editWindowLines[cursorOriginalLinesOffset].slice(cursorLineOffset - 1)]);
|
|
488
|
-
|
|
491
|
+
yield { edit, isFromCursorJump, window: editWindow };
|
|
489
492
|
const lines = [];
|
|
490
493
|
let v = await linesIter.next();
|
|
491
494
|
while (!v.done) {
|
|
@@ -498,13 +501,12 @@ let XtabProvider = class XtabProvider {
|
|
|
498
501
|
v = await linesIter.next();
|
|
499
502
|
}
|
|
500
503
|
const line = editWindowLineRange.start + cursorOriginalLinesOffset + 2;
|
|
501
|
-
|
|
504
|
+
yield {
|
|
502
505
|
edit: new lineEdit_1.LineReplacement(new lineRange_1.LineRange(line, line), lines),
|
|
503
506
|
isFromCursorJump,
|
|
504
507
|
window: editWindow
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
return;
|
|
508
|
+
};
|
|
509
|
+
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
508
510
|
}
|
|
509
511
|
if (trimmedLines === tags_1.ResponseTags.EDIT.start) {
|
|
510
512
|
cleanedLinesStream = new async_2.AsyncIterableObject(async (emitter) => {
|
|
@@ -519,8 +521,7 @@ let XtabProvider = class XtabProvider {
|
|
|
519
521
|
});
|
|
520
522
|
}
|
|
521
523
|
else {
|
|
522
|
-
|
|
523
|
-
return;
|
|
524
|
+
return new statelessNextEditProvider_1.NoNextEditReason.Unexpected(new Error(`unexpected tag ${trimmedLines}`));
|
|
524
525
|
}
|
|
525
526
|
}
|
|
526
527
|
else if (opts.responseFormat === xtabPromptOptions.ResponseFormat.CodeBlock) {
|
|
@@ -535,129 +536,110 @@ let XtabProvider = class XtabProvider {
|
|
|
535
536
|
nSignificantLinesToConverge: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabNSignificantLinesToConverge, this.expService),
|
|
536
537
|
};
|
|
537
538
|
tracer.trace(`starting to diff stream against edit window lines with latency ${fetchRequestStopWatch.elapsed()} ms`);
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
)
|
|
549
|
-
|
|
539
|
+
let i = 0;
|
|
540
|
+
let hasBeenDelayed = false;
|
|
541
|
+
try {
|
|
542
|
+
for await (const edit of responseProcessor_1.ResponseProcessor.diff(editWindowLines, cleanedLinesStream, cursorOriginalLinesOffset, diffOptions)) {
|
|
543
|
+
tracer.trace(`ResponseProcessor streamed edit #${i} with latency ${fetchRequestStopWatch.elapsed()} ms`);
|
|
544
|
+
const singleLineEdits = [];
|
|
545
|
+
if (edit.lineRange.startLineNumber === edit.lineRange.endLineNumberExclusive || // we don't want to run diff on insertion
|
|
546
|
+
edit.newLines.length === 0 || // we don't want to run diff on deletion
|
|
547
|
+
edit.lineRange.endLineNumberExclusive - edit.lineRange.startLineNumber === 1 && edit.newLines.length === 1 // we want to run diff on single line edits
|
|
548
|
+
) {
|
|
549
|
+
const singleLineEdit = new lineEdit_1.LineReplacement(new lineRange_1.LineRange(edit.lineRange.startLineNumber + editWindowLineRange.start, edit.lineRange.endLineNumberExclusive + editWindowLineRange.start), edit.newLines);
|
|
550
|
+
singleLineEdits.push(singleLineEdit);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
const affectedOriginalLines = editWindowLines.slice(edit.lineRange.startLineNumber - 1, edit.lineRange.endLineNumberExclusive - 1).join('\n');
|
|
554
|
+
const diffResult = await this.diffService.computeDiff(affectedOriginalLines, edit.newLines.join('\n'), {
|
|
555
|
+
ignoreTrimWhitespace: false,
|
|
556
|
+
maxComputationTimeMs: 0,
|
|
557
|
+
computeMoves: false
|
|
558
|
+
});
|
|
559
|
+
tracer.trace(`Ran diff for #${i} with latency ${fetchRequestStopWatch.elapsed()} ms`);
|
|
560
|
+
const translateByNLines = editWindowLineRange.start + edit.lineRange.startLineNumber;
|
|
561
|
+
for (const change of diffResult.changes) {
|
|
562
|
+
const singleLineEdit = new lineEdit_1.LineReplacement(new lineRange_1.LineRange(translateByNLines + change.original.startLineNumber - 1, translateByNLines + change.original.endLineNumberExclusive - 1), edit.newLines.slice(change.modified.startLineNumber - 1, change.modified.endLineNumberExclusive - 1));
|
|
550
563
|
singleLineEdits.push(singleLineEdit);
|
|
551
564
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
break;
|
|
568
|
-
}
|
|
569
|
-
logContext.setResponse(responseSoFar);
|
|
570
|
-
for (const singleLineEdit of singleLineEdits) {
|
|
571
|
-
tracer.trace(`pushing edit #${i}:\n${singleLineEdit.toString()}`);
|
|
572
|
-
if (!hasBeenDelayed) { // delay only the first one
|
|
573
|
-
hasBeenDelayed = true;
|
|
574
|
-
const artificialDelay = this.determineArtificialDelayMs(delaySession, tracer, telemetryBuilder);
|
|
575
|
-
if (artificialDelay) {
|
|
576
|
-
await (0, async_2.timeout)(artificialDelay);
|
|
577
|
-
tracer.trace(`Artificial delay of ${artificialDelay} ms completed`);
|
|
578
|
-
if (cancellationToken.isCancellationRequested) {
|
|
579
|
-
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterArtificialDelay')));
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
565
|
+
}
|
|
566
|
+
if (chatResponseFailure) { // do not emit edits if chat response failed
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
logContext.setResponse(responseSoFar);
|
|
570
|
+
for (const singleLineEdit of singleLineEdits) {
|
|
571
|
+
tracer.trace(`extracting edit #${i}: ${singleLineEdit.toString()}`);
|
|
572
|
+
if (!hasBeenDelayed) { // delay only the first one
|
|
573
|
+
hasBeenDelayed = true;
|
|
574
|
+
const artificialDelay = this.determineArtificialDelayMs(delaySession, tracer, telemetryBuilder);
|
|
575
|
+
if (artificialDelay) {
|
|
576
|
+
await (0, async_2.timeout)(artificialDelay);
|
|
577
|
+
tracer.trace(`Artificial delay of ${artificialDelay} ms completed`);
|
|
578
|
+
if (cancellationToken.isCancellationRequested) {
|
|
579
|
+
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterArtificialDelay');
|
|
582
580
|
}
|
|
583
581
|
}
|
|
584
|
-
pushEdit(result_1.Result.ok({ edit: singleLineEdit, isFromCursorJump, window: editWindow }));
|
|
585
|
-
i++;
|
|
586
582
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
pushEdit(result_1.Result.error(XtabProvider_1.mapChatFetcherErrorToNoNextEditReason(chatResponseFailure)));
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
const hadEdits = i > 0;
|
|
593
|
-
if (hadEdits) {
|
|
594
|
-
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
|
|
595
|
-
}
|
|
596
|
-
else {
|
|
597
|
-
await this.pushNoSuggestionsOrRetry(request, editWindow, promptPieces, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState);
|
|
583
|
+
yield { edit: singleLineEdit, isFromCursorJump, window: editWindow };
|
|
584
|
+
i++;
|
|
598
585
|
}
|
|
599
586
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
// Properly handle the error by pushing it as a result
|
|
603
|
-
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(err))));
|
|
587
|
+
if (chatResponseFailure) {
|
|
588
|
+
return XtabProvider_1.mapChatFetcherErrorToNoNextEditReason(chatResponseFailure);
|
|
604
589
|
}
|
|
605
|
-
|
|
606
|
-
}
|
|
607
|
-
async pushNoSuggestionsOrRetry(request, editWindow, promptPieces, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, retryState) {
|
|
608
|
-
const allowRetryWithExpandedWindow = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabProviderRetryWithNMoreLinesBelow, this.expService);
|
|
609
|
-
// if allowed to retry and not retrying already, flip the retry state and try again
|
|
610
|
-
if (allowRetryWithExpandedWindow && retryState instanceof RetryState.NotRetrying && request.expandedEditWindowNLines === undefined) {
|
|
611
|
-
this.doGetNextEdit(request, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, new RetryState.Retrying('expandedWindow'));
|
|
612
|
-
return;
|
|
590
|
+
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
613
591
|
}
|
|
592
|
+
catch (err) {
|
|
593
|
+
logContext.setError(err);
|
|
594
|
+
// Properly handle the error by pushing it as a result
|
|
595
|
+
return new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(err));
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
async *doGetNextEditsWithCursorJump(request, editWindow, promptPieces, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, retryState) {
|
|
599
|
+
const noSuggestions = new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
614
600
|
const nextCursorLinePrediction = this.nextCursorPredictor.determineEnablement();
|
|
615
|
-
if (nextCursorLinePrediction
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
601
|
+
if (nextCursorLinePrediction === undefined || retryState instanceof RetryState.Retrying) {
|
|
602
|
+
return noSuggestions;
|
|
603
|
+
}
|
|
604
|
+
const nextCursorLineR = await this.nextCursorPredictor.predictNextCursorPosition(promptPieces, tracer, telemetryBuilder, cancellationToken);
|
|
605
|
+
if (cancellationToken.isCancellationRequested) {
|
|
606
|
+
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterNextCursorPredictionFetch');
|
|
607
|
+
}
|
|
608
|
+
if (nextCursorLineR.isError()) {
|
|
609
|
+
tracer.trace(`Predicted next cursor line error: ${nextCursorLineR.err.message}`);
|
|
610
|
+
telemetryBuilder.setNextCursorLineError(nextCursorLineR.err.message);
|
|
611
|
+
return noSuggestions;
|
|
612
|
+
}
|
|
613
|
+
const nextCursorLineZeroBased = nextCursorLineR.val;
|
|
614
|
+
const lineDistanceFromCursorLine = nextCursorLineZeroBased - promptPieces.currentDocument.cursorLineOffset;
|
|
615
|
+
telemetryBuilder.setNextCursorLineDistance(lineDistanceFromCursorLine);
|
|
616
|
+
tracer.trace(`Predicted next cursor line: ${nextCursorLineZeroBased}`);
|
|
617
|
+
if (nextCursorLineZeroBased >= promptPieces.currentDocument.lines.length) { // >= because the line index is zero-based
|
|
618
|
+
tracer.trace(`Predicted next cursor line error: exceedsDocumentLines`);
|
|
619
|
+
telemetryBuilder.setNextCursorLineError('exceedsDocumentLines');
|
|
620
|
+
return noSuggestions;
|
|
621
|
+
}
|
|
622
|
+
if (promptPieces.editWindowLinesRange.contains(nextCursorLineZeroBased)) {
|
|
623
|
+
tracer.trace(`Predicted next cursor line error: withinEditWindow`);
|
|
624
|
+
telemetryBuilder.setNextCursorLineError('withinEditWindow');
|
|
625
|
+
return noSuggestions;
|
|
626
|
+
}
|
|
627
|
+
const nextCursorLineOneBased = nextCursorLineZeroBased + 1;
|
|
628
|
+
const nextCursorLine = promptPieces.activeDoc.documentAfterEditsLines.at(nextCursorLineZeroBased);
|
|
629
|
+
const nextCursorColumn = (nextCursorLine?.length ?? 0) + 1;
|
|
630
|
+
switch (nextCursorLinePrediction) {
|
|
631
|
+
case nextCursorLinePrediction_1.NextCursorLinePrediction.Jump: {
|
|
632
|
+
const nextCursorPosition = new position_1.Position(nextCursorLineOneBased, nextCursorColumn);
|
|
633
|
+
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow, nextCursorPosition);
|
|
620
634
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
635
|
+
case nextCursorLinePrediction_1.NextCursorLinePrediction.OnlyWithEdit: {
|
|
636
|
+
const v = this.doGetNextEditWithSelection(request, new range_1.Range(nextCursorLineOneBased, nextCursorColumn, nextCursorLineOneBased, nextCursorColumn), delaySession, tracer, logContext, cancellationToken, telemetryBuilder, new RetryState.Retrying('cursorJump'));
|
|
637
|
+
return yield* v;
|
|
624
638
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const lineDistanceFromCursorLine = nextCursorLineZeroBased - promptPieces.currentDocument.cursorLineOffset;
|
|
628
|
-
telemetryBuilder.setNextCursorLineDistance(lineDistanceFromCursorLine);
|
|
629
|
-
tracer.trace(`Predicted next cursor line: ${nextCursorLineZeroBased}`);
|
|
630
|
-
if (nextCursorLineZeroBased >= promptPieces.currentDocument.lines.length) { // >= because the line index is zero-based
|
|
631
|
-
tracer.trace(`Predicted next cursor line error: exceedsDocumentLines`);
|
|
632
|
-
telemetryBuilder.setNextCursorLineError('exceedsDocumentLines');
|
|
633
|
-
}
|
|
634
|
-
else if (promptPieces.editWindowLinesRange.contains(nextCursorLineZeroBased)) {
|
|
635
|
-
tracer.trace(`Predicted next cursor line error: withinEditWindow`);
|
|
636
|
-
telemetryBuilder.setNextCursorLineError('withinEditWindow');
|
|
637
|
-
}
|
|
638
|
-
else {
|
|
639
|
-
const nextCursorLineOneBased = nextCursorLineZeroBased + 1;
|
|
640
|
-
const nextCursorLine = promptPieces.activeDoc.documentAfterEditsLines.at(nextCursorLineZeroBased);
|
|
641
|
-
const nextCursorColumn = (nextCursorLine?.length ?? 0) + 1;
|
|
642
|
-
switch (nextCursorLinePrediction) {
|
|
643
|
-
case nextCursorLinePrediction_1.NextCursorLinePrediction.Jump: {
|
|
644
|
-
const nextCursorPosition = new position_1.Position(nextCursorLineOneBased, nextCursorColumn);
|
|
645
|
-
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow, nextCursorPosition)));
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
case nextCursorLinePrediction_1.NextCursorLinePrediction.OnlyWithEdit: {
|
|
649
|
-
this.doGetNextEditWithSelection(request, new range_1.Range(nextCursorLineOneBased, nextCursorColumn, nextCursorLineOneBased, nextCursorColumn), pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, new RetryState.Retrying('cursorJump'));
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
default: {
|
|
653
|
-
(0, assert_1.assertNever)(nextCursorLinePrediction);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
}
|
|
639
|
+
default: {
|
|
640
|
+
(0, assert_1.assertNever)(nextCursorLinePrediction);
|
|
657
641
|
}
|
|
658
642
|
}
|
|
659
|
-
pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
|
|
660
|
-
return;
|
|
661
643
|
}
|
|
662
644
|
computeAreaAroundEditWindowLinesRange(currentDocument) {
|
|
663
645
|
const cursorLine = currentDocument.cursorLineOffset;
|
|
@@ -665,7 +647,7 @@ let XtabProvider = class XtabProvider {
|
|
|
665
647
|
const areaAroundEndExcl = Math.min(currentDocument.lines.length, cursorLine + promptCrafting_1.N_LINES_AS_CONTEXT + 1);
|
|
666
648
|
return new offsetRange_1.OffsetRange(areaAroundStart, areaAroundEndExcl);
|
|
667
649
|
}
|
|
668
|
-
computeEditWindowLinesRange(currentDocument, request,
|
|
650
|
+
computeEditWindowLinesRange(currentDocument, request, tracer, telemetry) {
|
|
669
651
|
const currentDocLines = currentDocument.lines;
|
|
670
652
|
const cursorLineOffset = currentDocument.cursorLineOffset;
|
|
671
653
|
let nLinesAbove;
|
|
@@ -705,9 +687,6 @@ let XtabProvider = class XtabProvider {
|
|
|
705
687
|
nLinesBelow = promptCrafting_1.N_LINES_BELOW; // default
|
|
706
688
|
}
|
|
707
689
|
}
|
|
708
|
-
if (retryState instanceof RetryState.Retrying) {
|
|
709
|
-
nLinesBelow += this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabProviderRetryWithNMoreLinesBelow, this.expService) ?? 0;
|
|
710
|
-
}
|
|
711
690
|
let codeToEditStart = Math.max(0, cursorLineOffset - nLinesAbove);
|
|
712
691
|
let codeToEditEndExcl = Math.min(currentDocLines.length, cursorLineOffset + nLinesBelow + 1);
|
|
713
692
|
const maxMergeConflictLines = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabMaxMergeConflictLines, this.expService);
|
|
@@ -782,7 +761,8 @@ let XtabProvider = class XtabProvider {
|
|
|
782
761
|
languageContext: this.determineLanguageContextOptions(activeDocument.languageId, {
|
|
783
762
|
enabled: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabLanguageContextEnabled, this.expService),
|
|
784
763
|
enabledLanguages: this.configService.getConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabLanguageContextEnabledLanguages),
|
|
785
|
-
|
|
764
|
+
enableAllContextProviders: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Advanced.DiagnosticsContextProvider, this.expService)
|
|
765
|
+
|| this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Advanced.ChatSessionContextProvider, this.expService),
|
|
786
766
|
maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabLanguageContextMaxTokens, this.expService),
|
|
787
767
|
traitPosition: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabLanguageContextTraitsPosition, this.expService),
|
|
788
768
|
}),
|
|
@@ -834,11 +814,11 @@ let XtabProvider = class XtabProvider {
|
|
|
834
814
|
(0, assert_1.assertNever)(promptingStrategy);
|
|
835
815
|
}
|
|
836
816
|
}
|
|
837
|
-
determineLanguageContextOptions(languageId, { enabled, enabledLanguages, maxTokens,
|
|
817
|
+
determineLanguageContextOptions(languageId, { enabled, enabledLanguages, maxTokens, enableAllContextProviders, traitPosition }) {
|
|
838
818
|
if (languageId in enabledLanguages) {
|
|
839
819
|
return { enabled: enabledLanguages[languageId], maxTokens, traitPosition };
|
|
840
820
|
}
|
|
841
|
-
if (
|
|
821
|
+
if (enableAllContextProviders) {
|
|
842
822
|
return { enabled: true, maxTokens, traitPosition };
|
|
843
823
|
}
|
|
844
824
|
return { enabled, maxTokens, traitPosition };
|
|
@@ -904,6 +884,31 @@ let XtabProvider = class XtabProvider {
|
|
|
904
884
|
telemetry.setArtificialDelay(artificialDelay);
|
|
905
885
|
return artificialDelay;
|
|
906
886
|
}
|
|
887
|
+
filterEdit(activeDoc, edits) {
|
|
888
|
+
const filters = [
|
|
889
|
+
(edits) => importFiltering_1.IgnoreImportChangesAspect.filterEdit(activeDoc, edits),
|
|
890
|
+
(edits) => statelessNextEditProviders_1.IgnoreEmptyLineAndLeadingTrailingWhitespaceChanges.filterEdit(activeDoc, edits),
|
|
891
|
+
];
|
|
892
|
+
if (!this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.InlineEditsAllowWhitespaceOnlyChanges, this.expService)) {
|
|
893
|
+
filters.push((edits) => statelessNextEditProviders_1.IgnoreWhitespaceOnlyChanges.filterEdit(activeDoc, edits));
|
|
894
|
+
}
|
|
895
|
+
const undoInsertionFiltering = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsUndoInsertionFiltering, this.expService);
|
|
896
|
+
if (undoInsertionFiltering !== undefined) {
|
|
897
|
+
let filter;
|
|
898
|
+
switch (undoInsertionFiltering) {
|
|
899
|
+
case 'v1':
|
|
900
|
+
filter = statelessNextEditProviders_1.editWouldDeleteWhatWasJustInserted;
|
|
901
|
+
break;
|
|
902
|
+
case 'v2':
|
|
903
|
+
filter = statelessNextEditProviders_1.editWouldDeleteWhatWasJustInserted2;
|
|
904
|
+
break;
|
|
905
|
+
default:
|
|
906
|
+
(0, assert_1.assertNever)(undoInsertionFiltering);
|
|
907
|
+
}
|
|
908
|
+
filters.push((edits) => filter(activeDoc, new lineEdit_1.LineEdit(edits)) ? [] : edits);
|
|
909
|
+
}
|
|
910
|
+
return filters.reduce((acc, filter) => filter(acc), edits);
|
|
911
|
+
}
|
|
907
912
|
};
|
|
908
913
|
exports.XtabProvider = XtabProvider;
|
|
909
914
|
exports.XtabProvider = XtabProvider = XtabProvider_1 = __decorate([
|