@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.
Files changed (56) hide show
  1. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.d.ts.map +1 -1
  2. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js +3 -1
  3. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js.map +1 -1
  4. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts +16 -0
  5. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts.map +1 -1
  6. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js +57 -2
  7. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js.map +1 -1
  8. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.d.ts +2 -2
  9. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.d.ts.map +1 -1
  10. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js +15 -13
  11. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js.map +1 -1
  12. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.d.ts +3 -1
  13. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.d.ts.map +1 -1
  14. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js +4 -3
  15. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js.map +1 -1
  16. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts +5 -28
  17. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts.map +1 -1
  18. package/dist/src/_internal/extension/xtab/node/xtabProvider.js +197 -192
  19. package/dist/src/_internal/extension/xtab/node/xtabProvider.js.map +1 -1
  20. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts +14 -2
  21. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts.map +1 -1
  22. package/dist/src/_internal/platform/configuration/common/configurationService.js +8 -4
  23. package/dist/src/_internal/platform/configuration/common/configurationService.js.map +1 -1
  24. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts.map +1 -1
  25. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js +4 -0
  26. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js.map +1 -1
  27. package/dist/src/_internal/platform/endpoint/node/messagesApi.d.ts.map +1 -1
  28. package/dist/src/_internal/platform/endpoint/node/messagesApi.js +4 -2
  29. package/dist/src/_internal/platform/endpoint/node/messagesApi.js.map +1 -1
  30. package/dist/src/_internal/platform/git/common/gitService.d.ts +2 -1
  31. package/dist/src/_internal/platform/git/common/gitService.d.ts.map +1 -1
  32. package/dist/src/_internal/platform/git/common/gitService.js.map +1 -1
  33. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts +4 -0
  34. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts.map +1 -1
  35. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js +3 -0
  36. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js.map +1 -1
  37. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts +8 -2
  38. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts.map +1 -1
  39. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js +10 -0
  40. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js.map +1 -1
  41. package/dist/src/_internal/platform/networking/common/anthropic.d.ts +8 -8
  42. package/dist/src/_internal/platform/networking/common/anthropic.d.ts.map +1 -1
  43. package/dist/src/_internal/platform/networking/common/anthropic.js +33 -20
  44. package/dist/src/_internal/platform/networking/common/anthropic.js.map +1 -1
  45. package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts +8 -4
  46. package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts.map +1 -1
  47. package/dist/src/_internal/util/common/test/shims/chatTypes.js +13 -7
  48. package/dist/src/_internal/util/common/test/shims/chatTypes.js.map +1 -1
  49. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js +3 -3
  50. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js.map +1 -1
  51. package/dist/src/_internal/vscodeTypes.d.ts +1 -1
  52. package/dist/src/_internal/vscodeTypes.d.ts.map +1 -1
  53. package/dist/src/_internal/vscodeTypes.js +3 -3
  54. package/dist/src/_internal/vscodeTypes.js.map +1 -1
  55. package/dist/src/package.json +133 -20
  56. 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 nextEditResult = await this.doGetNextEdit(request, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetry, RetryState.NotRetrying.INSTANCE);
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
- async doGetNextEdit(request, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, retryState) {
198
- return this.doGetNextEditWithSelection(request, (0, nearbyCursorInlineEditProvider_1.getOrDeduceSelectionFromLastEdit)(request.getActiveDocument()), pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, retryState);
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, pushEdit, delaySession, parentTracer, logContext, cancellationToken, telemetryBuilder, retryState) {
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 result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('NoSelection')));
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, retryState, tracer, telemetryBuilder);
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 result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('editWindow'));
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 result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('currentFile'));
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 result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterLanguageContextAwait'));
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 result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('final'));
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 result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterDebounce'));
261
+ return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterDebounce');
278
262
  }
279
263
  request.fetchIssued = true;
280
264
  const cursorLineOffset = cursorPosition.column;
281
- this.streamEdits(request, pushEdit, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, editWindowLinesRange, promptPieces, prediction, {
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 streamEdits(request, pushEdit, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, // cursor offset within the line it's in; 1-based
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, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState); // use the same retry state
429
+ return yield* this.doGetNextEdit(request, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState); // use the same retry state
420
430
  }
421
- pushEdit(result_1.Result.error(XtabProvider_1.mapChatFetcherErrorToNoNextEditReason(fetchRes)));
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(pushEdit, linesStream, request.documentBeforeEdits, editWindow);
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
- pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(chatResponseFailure))));
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
- pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
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
- await this.pushNoSuggestionsOrRetry(request, editWindow, promptPieces, pushEdit, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState);
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
- pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
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
- pushEdit(result_1.Result.ok({ edit, isFromCursorJump, window: editWindow }));
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
- pushEdit(result_1.Result.ok({
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
- pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
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
- pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(new Error(`unexpected tag ${trimmedLines}`))));
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
- (async () => {
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);
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
- 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));
563
- singleLineEdits.push(singleLineEdit);
564
- }
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(`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
- if (chatResponseFailure) {
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
- catch (err) {
601
- logContext.setError(err);
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 !== undefined && retryState instanceof RetryState.NotRetrying) {
616
- const nextCursorLineR = await this.nextCursorPredictor.predictNextCursorPosition(promptPieces, tracer);
617
- if (cancellationToken.isCancellationRequested) {
618
- pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
619
- return;
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
- if (nextCursorLineR.isError()) {
622
- tracer.trace(`Predicted next cursor line error: ${nextCursorLineR.err.message}`);
623
- telemetryBuilder.setNextCursorLineError(nextCursorLineR.err.message);
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
- else {
626
- const nextCursorLineZeroBased = nextCursorLineR.val;
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, retryState, tracer, telemetry) {
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
- enabledDiagnostics: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Advanced.DiagnosticsContextProvider, this.expService),
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, enabledDiagnostics: diagnosticsEnabled, traitPosition }) {
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 (diagnosticsEnabled) {
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([