@vscode/chat-lib 0.4.1-0 → 0.4.1-10

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 (181) hide show
  1. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.js +1 -1
  2. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.js.map +1 -1
  3. package/dist/src/_internal/extension/inlineEdits/common/delay.d.ts +3 -1
  4. package/dist/src/_internal/extension/inlineEdits/common/delay.d.ts.map +1 -1
  5. package/dist/src/_internal/extension/inlineEdits/common/delay.js +6 -0
  6. package/dist/src/_internal/extension/inlineEdits/common/delay.js.map +1 -1
  7. package/dist/src/_internal/extension/inlineEdits/common/editRebase.d.ts.map +1 -1
  8. package/dist/src/_internal/extension/inlineEdits/common/editRebase.js +2 -35
  9. package/dist/src/_internal/extension/inlineEdits/common/editRebase.js.map +1 -1
  10. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.d.ts +6 -0
  11. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.d.ts.map +1 -1
  12. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.js +19 -35
  13. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.js.map +1 -1
  14. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts +1 -0
  15. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts.map +1 -1
  16. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts +12 -1
  17. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts.map +1 -1
  18. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js +150 -97
  19. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js.map +1 -1
  20. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.d.ts +7 -0
  21. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.d.ts.map +1 -1
  22. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js +18 -3
  23. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js.map +1 -1
  24. package/dist/src/_internal/extension/inlineEdits/node/nextEditResult.d.ts +2 -0
  25. package/dist/src/_internal/extension/inlineEdits/node/nextEditResult.d.ts.map +1 -1
  26. package/dist/src/_internal/extension/inlineEdits/node/nextEditResult.js.map +1 -1
  27. package/dist/src/_internal/extension/power/common/powerService.d.ts +11 -0
  28. package/dist/src/_internal/extension/power/common/powerService.d.ts.map +1 -1
  29. package/dist/src/_internal/extension/power/common/powerService.js +5 -0
  30. package/dist/src/_internal/extension/power/common/powerService.js.map +1 -1
  31. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts +11 -1
  32. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts.map +1 -1
  33. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js +235 -56
  34. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js.map +1 -1
  35. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.d.ts +26 -3
  36. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.d.ts.map +1 -1
  37. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.js +27 -9
  38. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.js.map +1 -1
  39. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.d.ts +6 -1
  40. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.d.ts.map +1 -1
  41. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.js +3 -1
  42. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.js.map +1 -1
  43. package/dist/src/_internal/extension/xtab/common/lintErrors.js +2 -1
  44. package/dist/src/_internal/extension/xtab/common/lintErrors.js.map +1 -1
  45. package/dist/src/_internal/extension/xtab/common/promptCrafting.d.ts +6 -1
  46. package/dist/src/_internal/extension/xtab/common/promptCrafting.d.ts.map +1 -1
  47. package/dist/src/_internal/extension/xtab/common/promptCrafting.js +43 -6
  48. package/dist/src/_internal/extension/xtab/common/promptCrafting.js.map +1 -1
  49. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.d.ts +22 -0
  50. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.d.ts.map +1 -1
  51. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.js +116 -17
  52. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.js.map +1 -1
  53. package/dist/src/_internal/extension/xtab/common/similarFilesContextService.d.ts +10 -0
  54. package/dist/src/_internal/extension/xtab/common/similarFilesContextService.d.ts.map +1 -0
  55. package/dist/src/_internal/extension/xtab/common/similarFilesContextService.js +10 -0
  56. package/dist/src/_internal/extension/xtab/common/similarFilesContextService.js.map +1 -0
  57. package/dist/src/_internal/extension/xtab/common/tags.d.ts +1 -0
  58. package/dist/src/_internal/extension/xtab/common/tags.d.ts.map +1 -1
  59. package/dist/src/_internal/extension/xtab/common/tags.js +1 -0
  60. package/dist/src/_internal/extension/xtab/common/tags.js.map +1 -1
  61. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js +1 -1
  62. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js.map +1 -1
  63. package/dist/src/_internal/extension/xtab/node/xtabEndpoint.d.ts.map +1 -1
  64. package/dist/src/_internal/extension/xtab/node/xtabEndpoint.js +1 -0
  65. package/dist/src/_internal/extension/xtab/node/xtabEndpoint.js.map +1 -1
  66. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.d.ts.map +1 -1
  67. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js +3 -2
  68. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js.map +1 -1
  69. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts +4 -1
  70. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts.map +1 -1
  71. package/dist/src/_internal/extension/xtab/node/xtabProvider.js +91 -20
  72. package/dist/src/_internal/extension/xtab/node/xtabProvider.js.map +1 -1
  73. package/dist/src/_internal/platform/authentication/common/copilotToken.d.ts +4 -0
  74. package/dist/src/_internal/platform/authentication/common/copilotToken.d.ts.map +1 -1
  75. package/dist/src/_internal/platform/authentication/common/copilotToken.js +6 -0
  76. package/dist/src/_internal/platform/authentication/common/copilotToken.js.map +1 -1
  77. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.js +1 -1
  78. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.js.map +1 -1
  79. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts +29 -24
  80. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts.map +1 -1
  81. package/dist/src/_internal/platform/configuration/common/configurationService.js +32 -19
  82. package/dist/src/_internal/platform/configuration/common/configurationService.js.map +1 -1
  83. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts +2 -1
  84. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts.map +1 -1
  85. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js +17 -7
  86. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js.map +1 -1
  87. package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts +1 -0
  88. package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts.map +1 -1
  89. package/dist/src/_internal/platform/endpoint/common/endpointProvider.js.map +1 -1
  90. package/dist/src/_internal/platform/endpoint/node/autoChatEndpoint.d.ts.map +1 -1
  91. package/dist/src/_internal/platform/endpoint/node/autoChatEndpoint.js +1 -0
  92. package/dist/src/_internal/platform/endpoint/node/autoChatEndpoint.js.map +1 -1
  93. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts +1 -0
  94. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts.map +1 -1
  95. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js +4 -3
  96. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js.map +1 -1
  97. package/dist/src/_internal/platform/endpoint/node/messagesApi.d.ts +6 -1
  98. package/dist/src/_internal/platform/endpoint/node/messagesApi.d.ts.map +1 -1
  99. package/dist/src/_internal/platform/endpoint/node/messagesApi.js +48 -15
  100. package/dist/src/_internal/platform/endpoint/node/messagesApi.js.map +1 -1
  101. package/dist/src/_internal/platform/endpoint/node/proxyXtabEndpoint.d.ts.map +1 -1
  102. package/dist/src/_internal/platform/endpoint/node/proxyXtabEndpoint.js +1 -0
  103. package/dist/src/_internal/platform/endpoint/node/proxyXtabEndpoint.js.map +1 -1
  104. package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts +1 -0
  105. package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts.map +1 -1
  106. package/dist/src/_internal/platform/endpoint/node/responsesApi.js +20 -2
  107. package/dist/src/_internal/platform/endpoint/node/responsesApi.js.map +1 -1
  108. package/dist/src/_internal/platform/github/common/githubService.d.ts +2 -1
  109. package/dist/src/_internal/platform/github/common/githubService.d.ts.map +1 -1
  110. package/dist/src/_internal/platform/github/common/githubService.js.map +1 -1
  111. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/triggerOptions.d.ts +8 -0
  112. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/triggerOptions.d.ts.map +1 -0
  113. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/triggerOptions.js +17 -0
  114. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/triggerOptions.js.map +1 -0
  115. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.d.ts +44 -0
  116. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.d.ts.map +1 -1
  117. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.js +71 -2
  118. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.js.map +1 -1
  119. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js +5 -5
  120. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js.map +1 -1
  121. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts +15 -1
  122. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts.map +1 -1
  123. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js +22 -1
  124. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js.map +1 -1
  125. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.d.ts.map +1 -1
  126. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.js +9 -44
  127. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.js.map +1 -1
  128. package/dist/src/_internal/platform/nesFetch/common/responseStream.js +2 -35
  129. package/dist/src/_internal/platform/nesFetch/common/responseStream.js.map +1 -1
  130. package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.js +3 -36
  131. package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.js.map +1 -1
  132. package/dist/src/_internal/platform/networking/common/anthropic.d.ts +11 -16
  133. package/dist/src/_internal/platform/networking/common/anthropic.d.ts.map +1 -1
  134. package/dist/src/_internal/platform/networking/common/anthropic.js +33 -38
  135. package/dist/src/_internal/platform/networking/common/anthropic.js.map +1 -1
  136. package/dist/src/_internal/platform/networking/common/fetcherService.d.ts +43 -1
  137. package/dist/src/_internal/platform/networking/common/fetcherService.d.ts.map +1 -1
  138. package/dist/src/_internal/platform/networking/common/fetcherService.js +29 -4
  139. package/dist/src/_internal/platform/networking/common/fetcherService.js.map +1 -1
  140. package/dist/src/_internal/platform/networking/common/networking.d.ts +40 -4
  141. package/dist/src/_internal/platform/networking/common/networking.d.ts.map +1 -1
  142. package/dist/src/_internal/platform/networking/common/networking.js +21 -6
  143. package/dist/src/_internal/platform/networking/common/networking.js.map +1 -1
  144. package/dist/src/_internal/platform/networking/node/chatWebSocketManager.d.ts +71 -0
  145. package/dist/src/_internal/platform/networking/node/chatWebSocketManager.d.ts.map +1 -0
  146. package/dist/src/_internal/platform/networking/node/chatWebSocketManager.js +308 -0
  147. package/dist/src/_internal/platform/networking/node/chatWebSocketManager.js.map +1 -0
  148. package/dist/src/_internal/platform/proxyModels/node/proxyModelsService.js +4 -37
  149. package/dist/src/_internal/platform/proxyModels/node/proxyModelsService.js.map +1 -1
  150. package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.d.ts +1 -0
  151. package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.d.ts.map +1 -1
  152. package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.js +3 -0
  153. package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.js.map +1 -1
  154. package/dist/src/_internal/platform/requestLogger/node/requestLogger.d.ts +2 -0
  155. package/dist/src/_internal/platform/requestLogger/node/requestLogger.d.ts.map +1 -1
  156. package/dist/src/_internal/platform/requestLogger/node/requestLogger.js.map +1 -1
  157. package/dist/src/_internal/platform/telemetry/common/telemetry.d.ts +9 -1
  158. package/dist/src/_internal/platform/telemetry/common/telemetry.d.ts.map +1 -1
  159. package/dist/src/_internal/platform/telemetry/common/telemetry.js +33 -15
  160. package/dist/src/_internal/platform/telemetry/common/telemetry.js.map +1 -1
  161. package/dist/src/_internal/platform/telemetry/node/azureInsightsReporter.d.ts +1 -1
  162. package/dist/src/_internal/platform/telemetry/node/azureInsightsReporter.d.ts.map +1 -1
  163. package/dist/src/_internal/platform/telemetry/node/azureInsightsReporter.js +3 -2
  164. package/dist/src/_internal/platform/telemetry/node/azureInsightsReporter.js.map +1 -1
  165. package/dist/src/_internal/util/common/errors.d.ts +4 -2
  166. package/dist/src/_internal/util/common/errors.d.ts.map +1 -1
  167. package/dist/src/_internal/util/common/errors.js +16 -12
  168. package/dist/src/_internal/util/common/errors.js.map +1 -1
  169. package/dist/src/_internal/util/common/result.js +4 -37
  170. package/dist/src/_internal/util/common/result.js.map +1 -1
  171. package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts +14 -2
  172. package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts.map +1 -1
  173. package/dist/src/_internal/util/common/test/shims/chatTypes.js +17 -3
  174. package/dist/src/_internal/util/common/test/shims/chatTypes.js.map +1 -1
  175. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js +1 -1
  176. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js.map +1 -1
  177. package/dist/src/main.d.ts.map +1 -1
  178. package/dist/src/main.js +10 -0
  179. package/dist/src/main.js.map +1 -1
  180. package/dist/src/package.json +221 -294
  181. package/package.json +2 -2
@@ -3,54 +3,23 @@
3
3
  * Copyright (c) Microsoft Corporation. All rights reserved.
4
4
  * Licensed under the MIT License. See License.txt in the project root for license information.
5
5
  *--------------------------------------------------------------------------------------------*/
6
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
- if (k2 === undefined) k2 = k;
8
- var desc = Object.getOwnPropertyDescriptor(m, k);
9
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
- desc = { enumerable: true, get: function() { return m[k]; } };
11
- }
12
- Object.defineProperty(o, k2, desc);
13
- }) : (function(o, m, k, k2) {
14
- if (k2 === undefined) k2 = k;
15
- o[k2] = m[k];
16
- }));
17
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
- Object.defineProperty(o, "default", { enumerable: true, value: v });
19
- }) : function(o, v) {
20
- o["default"] = v;
21
- });
22
6
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
23
7
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
24
8
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
25
9
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
26
10
  return c > 3 && r && Object.defineProperty(target, key, r), r;
27
11
  };
28
- var __importStar = (this && this.__importStar) || (function () {
29
- var ownKeys = function(o) {
30
- ownKeys = Object.getOwnPropertyNames || function (o) {
31
- var ar = [];
32
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
- return ar;
34
- };
35
- return ownKeys(o);
36
- };
37
- return function (mod) {
38
- if (mod && mod.__esModule) return mod;
39
- var result = {};
40
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
- __setModuleDefault(result, mod);
42
- return result;
43
- };
44
- })();
45
12
  var __param = (this && this.__param) || function (paramIndex, decorator) {
46
13
  return function (target, key) { decorator(target, key, paramIndex); }
47
14
  };
15
+ var NextEditProvider_1;
48
16
  Object.defineProperty(exports, "__esModule", { value: true });
49
- exports.NextEditFetchRequest = exports.NextEditProvider = void 0;
17
+ exports.NextEditFetchRequest = exports.NextEditProvider = exports.NesOutcome = void 0;
50
18
  const path_1 = require("path");
51
19
  const configurationService_1 = require("../../../platform/configuration/common/configurationService");
52
20
  const edit_1 = require("../../../platform/inlineEdits/common/dataTypes/edit");
53
21
  const rootedLineEdit_1 = require("../../../platform/inlineEdits/common/dataTypes/rootedLineEdit");
22
+ const xtabPromptOptions_1 = require("../../../platform/inlineEdits/common/dataTypes/xtabPromptOptions");
54
23
  const inlineEditLogContext_1 = require("../../../platform/inlineEdits/common/inlineEditLogContext");
55
24
  const statelessNextEditProvider_1 = require("../../../platform/inlineEdits/common/statelessNextEditProvider");
56
25
  const observable_1 = require("../../../platform/inlineEdits/common/utils/observable");
@@ -59,12 +28,12 @@ const capturingToken_1 = require("../../../platform/requestLogger/common/capturi
59
28
  const requestLogger_1 = require("../../../platform/requestLogger/node/requestLogger");
60
29
  const snippyService_1 = require("../../../platform/snippy/common/snippyService");
61
30
  const nullExperimentationService_1 = require("../../../platform/telemetry/common/nullExperimentationService");
62
- const errors = __importStar(require("../../../util/common/errors"));
31
+ const errors_1 = require("../../../util/common/errors");
63
32
  const result_1 = require("../../../util/common/result");
64
33
  const assert_1 = require("../../../util/vs/base/common/assert");
65
34
  const async_1 = require("../../../util/vs/base/common/async");
66
35
  const cache_1 = require("../../../util/vs/base/common/cache");
67
- const errors_1 = require("../../../util/vs/base/common/errors");
36
+ const errors_2 = require("../../../util/vs/base/common/errors");
68
37
  const lifecycle_1 = require("../../../util/vs/base/common/lifecycle");
69
38
  const observable_2 = require("../../../util/vs/base/common/observable");
70
39
  const stopwatch_1 = require("../../../util/vs/base/common/stopwatch");
@@ -106,13 +75,22 @@ function convertLineEditToEdit(nextLineEdit, projectedDocuments, docId) {
106
75
  const suggestedEdit = rootedLineEdit.toEdit();
107
76
  return suggestedEdit;
108
77
  }
109
- let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
78
+ var NesOutcome;
79
+ (function (NesOutcome) {
80
+ NesOutcome["Accepted"] = "accepted";
81
+ NesOutcome["Rejected"] = "rejected";
82
+ NesOutcome["Ignored"] = "ignored";
83
+ })(NesOutcome || (exports.NesOutcome = NesOutcome = {}));
84
+ let NextEditProvider = NextEditProvider_1 = class NextEditProvider extends lifecycle_1.Disposable {
110
85
  get lastRejectionTime() {
111
86
  return this._lastRejectionTime;
112
87
  }
113
88
  get lastTriggerTime() {
114
89
  return this._lastTriggerTime;
115
90
  }
91
+ get lastOutcome() {
92
+ return this._lastOutcome;
93
+ }
116
94
  constructor(_workspace, _statelessNextEditProvider, _historyContextProvider, _xtabHistoryTracker, _debugRecorder, _configService, _snippyService, _logService, _expService, _requestLogger) {
117
95
  super();
118
96
  this._workspace = _workspace;
@@ -148,7 +126,20 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
148
126
  }));
149
127
  }).recomputeInitiallyAndOnChange(this._store);
150
128
  }
129
+ _cancelSpeculativeRequest() {
130
+ if (this._speculativePendingRequest) {
131
+ this._speculativePendingRequest.request.cancellationTokenSource.cancel();
132
+ this._speculativePendingRequest = null;
133
+ }
134
+ }
151
135
  _cancelPendingRequestDueToDocChange(docId, docValue) {
136
+ // Note: we intentionally do NOT cancel the speculative request here.
137
+ // The speculative request's postEditContent represents a *future* document state
138
+ // (after the user would accept the suggestion), so it will almost never match the
139
+ // current document value while the user is still typing. Cancelling here would
140
+ // wastefully kill and recreate the speculative request on every keystroke.
141
+ // Instead, speculative requests are cancelled by the appropriate lifecycle handlers:
142
+ // handleRejection, handleIgnored, _triggerSpeculativeRequest, and _executeNewNextEditRequest.
152
143
  const isAsyncCompletions = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAsyncCompletions, this._expService);
153
144
  if (isAsyncCompletions || this._pendingStatelessNextEditRequest === null) {
154
145
  return;
@@ -174,7 +165,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
174
165
  }
175
166
  catch (error) {
176
167
  logContext.setError(error);
177
- telemetryBuilder.setNextEditProviderError(errors.toString(error));
168
+ telemetryBuilder.setNextEditProviderError(errors_1.ErrorUtils.toString(error));
178
169
  throw error;
179
170
  }
180
171
  finally {
@@ -189,7 +180,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
189
180
  const doc = this._workspace.getDocument(docId);
190
181
  if (!doc) {
191
182
  logger.trace(`Document "${docId.baseName}" not found`);
192
- throw new errors_1.BugIndicatingError(`Document "${docId.baseName}" not found`);
183
+ throw new errors_2.BugIndicatingError(`Document "${docId.baseName}" not found`);
193
184
  }
194
185
  const documentAtInvocationTime = doc.value.get();
195
186
  const selections = doc.selection.get();
@@ -209,6 +200,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
209
200
  let targetDocumentId = docId;
210
201
  let isRebasedCachedEdit = false;
211
202
  let isSubsequentCachedEdit = false;
203
+ let isFromSpeculativeRequest = false;
212
204
  if (cachedEdit) {
213
205
  logger.trace('using cached edit');
214
206
  const actualEdit = cachedEdit.rebasedEdit || cachedEdit.edit;
@@ -231,7 +223,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
231
223
  const providerRequestStartDateTime = (this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsDebounceUseCoreRequestTime, this._expService)
232
224
  ? (context.requestIssuedDateTime ?? undefined)
233
225
  : undefined);
234
- req = new NextEditFetchRequest(context.requestUuid, logContext, providerRequestStartDateTime);
226
+ req = new NextEditFetchRequest(context.requestUuid, logContext, providerRequestStartDateTime, false);
235
227
  telemetryBuilder.setHeaderRequestId(req.headerRequestId);
236
228
  const startVersion = doc.value.get();
237
229
  logger.trace('awaiting firstEdit promise');
@@ -265,6 +257,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
265
257
  logger.trace('fetch succeeded');
266
258
  logContext.setResponseResults([suggestedNextEdit]); // TODO: other streamed edits?
267
259
  edit = { actualEdit: suggestedNextEdit, isFromCursorJump: result.val.isFromCursorJump };
260
+ isFromSpeculativeRequest = result.val.isFromSpeculativeRequest ?? false;
268
261
  }
269
262
  }
270
263
  }
@@ -279,7 +272,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
279
272
  }
280
273
  else {
281
274
  telemetryBuilder.setStatus('emptyEditsButHasNextCursorPosition');
282
- return new nextEditResult_1.NextEditResult(logContext.requestId, req, { jumpToPosition: error.nextCursorPosition, documentBeforeEdits: documentAtInvocationTime, isFromCursorJump: false });
275
+ return new nextEditResult_1.NextEditResult(logContext.requestId, req, { jumpToPosition: error.nextCursorPosition, documentBeforeEdits: documentAtInvocationTime, isFromCursorJump: false, isSubsequentEdit: false });
283
276
  }
284
277
  }
285
278
  const emptyResult = new nextEditResult_1.NextEditResult(logContext.requestId, req, undefined);
@@ -302,9 +295,9 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
302
295
  logContext.setResult(rootedLineEdit_1.RootedLineEdit.fromEdit(new edit_1.RootedEdit(documentAtInvocationTime, new stringEdit_1.StringEdit([edit.actualEdit]))));
303
296
  (0, assert_1.assert)(currentDocument !== undefined, 'should be defined if edit is defined');
304
297
  telemetryBuilder.setStatus('notAccepted'); // Acceptance pending.
305
- const nextEditResult = new nextEditResult_1.NextEditResult(logContext.requestId, req, { edit: edit.actualEdit, isFromCursorJump: edit.isFromCursorJump, documentBeforeEdits: currentDocument, targetDocumentId });
298
+ const nextEditResult = new nextEditResult_1.NextEditResult(logContext.requestId, req, { edit: edit.actualEdit, isFromCursorJump: edit.isFromCursorJump, documentBeforeEdits: currentDocument, targetDocumentId, isSubsequentEdit: isSubsequentCachedEdit });
306
299
  telemetryBuilder.setHasNextEdit(true);
307
- const delay = this.computeMinimumResponseDelay({ triggerTime, isRebasedCachedEdit, isSubsequentCachedEdit, enforceCacheDelay: context.enforceCacheDelay }, logger);
300
+ const delay = this.computeMinimumResponseDelay({ triggerTime, isRebasedCachedEdit, isSubsequentCachedEdit, isFromSpeculativeRequest, enforceCacheDelay: context.enforceCacheDelay }, logger);
308
301
  if (delay > 0) {
309
302
  await (0, async_1.timeout)(delay);
310
303
  if (cancellationToken.isCancellationRequested) {
@@ -355,7 +348,8 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
355
348
  const existingNextEditRequest = (pendingRequestStillCurrent || nesConfigs.isAsyncCompletions) && !this._pendingStatelessNextEditRequest?.cancellationTokenSource.token.isCancellationRequested
356
349
  && this._pendingStatelessNextEditRequest || undefined;
357
350
  // Check if we can reuse the speculative pending request (from when a suggestion was shown)
358
- const speculativeRequestMatches = this._speculativePendingRequest?.postEditContent === documentAtInvocationTime.value
351
+ const speculativeRequestMatches = this._speculativePendingRequest?.docId === curDocId
352
+ && this._speculativePendingRequest?.postEditContent === documentAtInvocationTime.value
359
353
  && !this._speculativePendingRequest.request.cancellationTokenSource.token.isCancellationRequested;
360
354
  const speculativeRequest = speculativeRequestMatches ? this._speculativePendingRequest?.request : undefined;
361
355
  // Prefer speculative request if it matches (it was specifically created for this post-edit state)
@@ -370,9 +364,14 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
370
364
  const requestStillCurrent = speculativeRequest
371
365
  ? speculativeRequestMatches // For speculative, we already checked it matches
372
366
  : pendingRequestStillCurrent;
367
+ const reusedRequestKind = speculativeRequest ? "speculative" /* ReusedRequestKind.Speculative */ : "async" /* ReusedRequestKind.Async */;
373
368
  if (requestStillCurrent) {
374
- const nextEditResult = await this._joinNextEditRequest(requestToReuse, telemetryBuilder, logContext, cancellationToken);
369
+ const nextEditResult = await this._joinNextEditRequest(requestToReuse, reusedRequestKind, telemetryBuilder, logContext, cancellationToken);
375
370
  telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
371
+ if (speculativeRequest) {
372
+ const firstEdit = await requestToReuse.firstEdit.p;
373
+ return firstEdit.map(val => ({ ...val, isFromSpeculativeRequest: true }));
374
+ }
376
375
  return nextEditResult.nextEdit.isError() ? nextEditResult.nextEdit : requestToReuse.firstEdit.p;
377
376
  }
378
377
  else if (nesConfigs.isEagerBackupRequest) {
@@ -390,7 +389,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
390
389
  .catch(() => undefined);
391
390
  };
392
391
  // Simultaneously attempt to join + rebase the stale request
393
- const nextEditResult = await this._joinNextEditRequest(requestToReuse, telemetryBuilder, logContext, cancellationToken);
392
+ const nextEditResult = await this._joinNextEditRequest(requestToReuse, reusedRequestKind, telemetryBuilder, logContext, cancellationToken);
394
393
  const cacheResult = await requestToReuse.firstEdit.p;
395
394
  if (cacheResult.isOk() && cacheResult.val.edit) {
396
395
  const rebasedCachedEdit = this._nextEditCache.tryRebaseCacheEntry(cacheResult.val, documentAtInvocationTime, selectionAtInvocationTime);
@@ -414,7 +413,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
414
413
  return backupRes.nextEditResult.nextEdit.isError() ? backupRes.nextEditResult.nextEdit : backupRes.nextEditRequest.firstEdit.p;
415
414
  }
416
415
  else {
417
- const nextEditResult = await this._joinNextEditRequest(requestToReuse, telemetryBuilder, logContext, cancellationToken);
416
+ const nextEditResult = await this._joinNextEditRequest(requestToReuse, reusedRequestKind, telemetryBuilder, logContext, cancellationToken);
418
417
  // Needs rebasing.
419
418
  const cacheResult = await requestToReuse.firstEdit.p;
420
419
  if (cacheResult.isOk() && cacheResult.val.edit) {
@@ -435,7 +434,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
435
434
  && this._pendingStatelessNextEditRequest || undefined;
436
435
  if (existingNextEditRequest2) {
437
436
  logger.trace('reusing 2nd existing next edit request after rebase failed');
438
- const nextEditResult2 = await this._joinNextEditRequest(existingNextEditRequest2, telemetryBuilder, logContext, cancellationToken);
437
+ const nextEditResult2 = await this._joinNextEditRequest(existingNextEditRequest2, "async" /* ReusedRequestKind.Async */, telemetryBuilder, logContext, cancellationToken);
439
438
  telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult2.telemetry);
440
439
  return nextEditResult2.nextEdit.isError() ? nextEditResult2.nextEdit : existingNextEditRequest2.firstEdit.p;
441
440
  }
@@ -448,10 +447,9 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
448
447
  telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
449
448
  return nextEditResult.nextEdit.isError() ? nextEditResult.nextEdit : nextEditRequest.firstEdit.p;
450
449
  }
451
- async _joinNextEditRequest(nextEditRequest, telemetryBuilder, logContext, cancellationToken) {
452
- // TODO: Will the telemetry look alright in this case?
450
+ async _joinNextEditRequest(nextEditRequest, reusedRequestKind, telemetryBuilder, logContext, cancellationToken) {
453
451
  telemetryBuilder.setHeaderRequestId(nextEditRequest.headerRequestId);
454
- telemetryBuilder.setIsFromCache();
452
+ telemetryBuilder.setReusedRequest(reusedRequestKind);
455
453
  telemetryBuilder.setRequest(nextEditRequest);
456
454
  logContext.setRequestInput(nextEditRequest);
457
455
  logContext.setIsCachedResult(nextEditRequest.logContext);
@@ -476,12 +474,20 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
476
474
  const nLinesEditWindow = (shouldExpandEditWindow
477
475
  ? this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAutoExpandEditWindowLines, this._expService)
478
476
  : undefined);
479
- const nextEditRequest = new statelessNextEditProvider_1.StatelessNextEditRequest(req.headerRequestId, req.opportunityId, doc.value.get(), projectedDocuments.map(d => d.nextEditDoc), activeDocAndIdx.idx, xtabEditHistory, firstEdit, nLinesEditWindow, logContext, req.log.recordingBookmark, recording, req.providerRequestStartDateTime);
477
+ const nextEditRequest = new statelessNextEditProvider_1.StatelessNextEditRequest(req.headerRequestId, req.opportunityId, doc.value.get(), projectedDocuments.map(d => d.nextEditDoc), activeDocAndIdx.idx, xtabEditHistory, firstEdit, nLinesEditWindow, false, // isSpeculative
478
+ logContext, req.log.recordingBookmark, recording, req.providerRequestStartDateTime);
480
479
  let nextEditResult;
481
480
  if (this._pendingStatelessNextEditRequest) {
482
481
  this._pendingStatelessNextEditRequest.cancellationTokenSource.cancel();
483
482
  this._pendingStatelessNextEditRequest = null;
484
483
  }
484
+ // Cancel speculative request if it doesn't match the document/state
485
+ // of this new request — it was built for a different document or post-edit state.
486
+ if (this._speculativePendingRequest
487
+ && (this._speculativePendingRequest.docId !== curDocId
488
+ || this._speculativePendingRequest.postEditContent !== nextEditRequest.documentBeforeEdits.value)) {
489
+ this._cancelSpeculativeRequest();
490
+ }
485
491
  this._pendingStatelessNextEditRequest = nextEditRequest;
486
492
  const removeFromPending = () => {
487
493
  if (this._pendingStatelessNextEditRequest === nextEditRequest) {
@@ -513,7 +519,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
513
519
  const statePerDoc = new cache_1.CachedFunction((id) => {
514
520
  const doc = projectedDocuments.find(d => d.nextEditDoc.id === id);
515
521
  if (!doc) {
516
- throw new errors_1.BugIndicatingError();
522
+ throw new errors_2.BugIndicatingError();
517
523
  }
518
524
  return {
519
525
  docContents: doc.documentAfterEdits,
@@ -623,8 +629,8 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
623
629
  handleStreamEnd(completionReason, res.value.telemetryBuilder);
624
630
  }
625
631
  catch (err) {
626
- logger.trace(`Error while streaming further edits: ${errors.toString(err)}`);
627
- const errorReason = new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(err));
632
+ logger.trace(`Error while streaming further edits: ${errors_1.ErrorUtils.toString(err)}`);
633
+ const errorReason = new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors_1.ErrorUtils.fromUnknown(err));
628
634
  handleStreamEnd(errorReason, firstTelemetry);
629
635
  }
630
636
  })();
@@ -678,7 +684,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
678
684
  nextEditRequest.liveDependentants++;
679
685
  return disposables;
680
686
  }
681
- computeMinimumResponseDelay({ triggerTime, isRebasedCachedEdit, isSubsequentCachedEdit, enforceCacheDelay }, logger) {
687
+ computeMinimumResponseDelay({ triggerTime, isRebasedCachedEdit, isSubsequentCachedEdit, isFromSpeculativeRequest, enforceCacheDelay }, logger) {
682
688
  if (!enforceCacheDelay) {
683
689
  logger.trace('[minimumDelay] no minimum delay enforced due to enforceCacheDelay being false');
684
690
  return 0;
@@ -686,6 +692,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
686
692
  const cacheDelay = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsCacheDelay, this._expService);
687
693
  const rebasedCacheDelay = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsRebasedCacheDelay, this._expService);
688
694
  const subsequentCacheDelay = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSubsequentCacheDelay, this._expService);
695
+ const speculativeRequestDelay = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSpeculativeRequestDelay, this._expService);
689
696
  let minimumResponseDelay = cacheDelay;
690
697
  if (isRebasedCachedEdit && rebasedCacheDelay !== undefined) {
691
698
  minimumResponseDelay = rebasedCacheDelay;
@@ -693,18 +700,22 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
693
700
  else if (isSubsequentCachedEdit && subsequentCacheDelay !== undefined) {
694
701
  minimumResponseDelay = subsequentCacheDelay;
695
702
  }
703
+ else if (isFromSpeculativeRequest && speculativeRequestDelay !== undefined) {
704
+ minimumResponseDelay = speculativeRequestDelay;
705
+ }
696
706
  const nextEditProviderCallLatency = Date.now() - triggerTime;
697
707
  // if the provider call took longer than the minimum delay, we don't need to delay further
698
708
  const delay = Math.max(0, minimumResponseDelay - nextEditProviderCallLatency);
699
- logger.trace(`[minimumDelay] expected delay: ${minimumResponseDelay}ms, effective delay: ${delay}. isRebasedCachedEdit: ${isRebasedCachedEdit} (rebasedCacheDelay: ${rebasedCacheDelay}), isSubsequentCachedEdit: ${isSubsequentCachedEdit} (subsequentCacheDelay: ${subsequentCacheDelay})`);
709
+ logger.trace(`[minimumDelay] expected delay: ${minimumResponseDelay}ms, effective delay: ${delay}. isRebasedCachedEdit: ${isRebasedCachedEdit} (rebasedCacheDelay: ${rebasedCacheDelay}), isSubsequentCachedEdit: ${isSubsequentCachedEdit} (subsequentCacheDelay: ${subsequentCacheDelay}), isFromSpeculativeRequest: ${isFromSpeculativeRequest} (speculativeRequestDelay: ${speculativeRequestDelay})`);
700
710
  return delay;
701
711
  }
702
712
  handleShown(suggestion) {
703
713
  this._lastShownTime = Date.now();
704
714
  this._lastShownSuggestionId = suggestion.requestId;
715
+ this._lastOutcome = undefined; // clear so that outcome is "pending" until resolved
705
716
  // Trigger speculative request for the post-edit document state
706
- const speculativeRequestsEnabled = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSpeculativeRequests, this._expService);
707
- if (speculativeRequestsEnabled) {
717
+ const speculativeRequestsEnablement = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSpeculativeRequests, this._expService);
718
+ if (speculativeRequestsEnablement === xtabPromptOptions_1.SpeculativeRequestsEnablement.On) {
708
719
  void this._triggerSpeculativeRequest(suggestion);
709
720
  }
710
721
  }
@@ -722,12 +733,14 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
722
733
  }
723
734
  // Compute the post-edit document content
724
735
  const postEditContent = result.edit.replace(result.documentBeforeEdits.value);
725
- const postEditCursorOffset = result.edit.replaceRange.endExclusive + result.edit.getLengthDelta();
726
- const selections = [new offsetRange_1.OffsetRange(postEditCursorOffset, postEditCursorOffset)];
736
+ const preciseEdit = result.edit.removeCommonSuffixPrefix(result.documentBeforeEdits.value);
737
+ const postEditCursorOffset = preciseEdit.replaceRange.start + preciseEdit.newText.length;
738
+ const postEditCursorOffsetRange = new offsetRange_1.OffsetRange(postEditCursorOffset, postEditCursorOffset);
739
+ const selections = [postEditCursorOffsetRange];
727
740
  const rootedEdit = new edit_1.RootedEdit(result.documentBeforeEdits, new stringEdit_1.StringEdit([result.edit]));
728
741
  const postEditContentST = new abstractText_1.StringText(postEditContent);
729
742
  let cachedEdit = this._nextEditCache.lookupNextEdit(docId, postEditContentST, selections);
730
- let shiftedSelection;
743
+ let shiftedSelection = postEditCursorOffsetRange;
731
744
  if (cachedEdit) {
732
745
  // first cachedEdit should be without edits because of noSuggestions caching
733
746
  if (cachedEdit.edit) {
@@ -735,17 +748,22 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
735
748
  return;
736
749
  }
737
750
  else if (cachedEdit.editWindow) {
738
- const trans = postEditContentST.getTransformer();
739
- const endOfEditWindow = trans.getPosition(cachedEdit.editWindow.endExclusive - 1);
740
- const shiftedCursorLineNumber = (endOfEditWindow.lineNumber + 1 < postEditContentST.lineRange.endLineNumberExclusive
741
- ? endOfEditWindow.lineNumber + 1
742
- : endOfEditWindow.lineNumber);
743
- const shiftedSelectionCursorOffset = trans.getOffset(new position_1.Position(shiftedCursorLineNumber, 1));
744
- shiftedSelection = new offsetRange_1.OffsetRange(shiftedSelectionCursorOffset, shiftedSelectionCursorOffset);
745
- cachedEdit = this._nextEditCache.lookupNextEdit(docId, postEditContentST, [shiftedSelection]);
746
- if (cachedEdit?.edit) {
747
- logger.trace('already have cached edit for post-edit state (after shifting selection)');
748
- return;
751
+ logger.trace('have cached no-suggestions entry for post-edit state, but it has an edit window. Checking if shifting selection based on cursor placement config can yield a cached edit');
752
+ const cursorPlacement = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSpeculativeRequestsCursorPlacement, this._expService);
753
+ if (cursorPlacement === xtabPromptOptions_1.SpeculativeRequestsCursorPlacement.AfterEditWindow) {
754
+ logger.trace('cursor placement config is AfterEditWindow, shifting selection to after edit window');
755
+ shiftedSelection = NextEditProvider_1.shiftSelectionAfterEditWindow(postEditContentST, cachedEdit.editWindow);
756
+ cachedEdit = this._nextEditCache.lookupNextEdit(docId, postEditContentST, [shiftedSelection]);
757
+ if (cachedEdit?.edit) {
758
+ logger.trace('already have cached edit for post-edit state (after shifting selection)');
759
+ return;
760
+ }
761
+ else {
762
+ logger.trace('no cached edit even after shifting selection');
763
+ }
764
+ }
765
+ else {
766
+ logger.trace(`cursor placement config is ${cursorPlacement}, not shifting selection`);
749
767
  }
750
768
  }
751
769
  else {
@@ -759,7 +777,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
759
777
  return;
760
778
  }
761
779
  // Check if we already have a speculative request for this post-edit state
762
- if (this._speculativePendingRequest?.postEditContent === postEditContent) {
780
+ if (this._speculativePendingRequest?.docId === docId && this._speculativePendingRequest?.postEditContent === postEditContent) {
763
781
  logger.trace('already have speculative request for post-edit state');
764
782
  return;
765
783
  }
@@ -772,8 +790,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
772
790
  return;
773
791
  }
774
792
  // Cancel any previous speculative request
775
- this._speculativePendingRequest?.request.cancellationTokenSource.cancel();
776
- this._speculativePendingRequest = null;
793
+ this._cancelSpeculativeRequest();
777
794
  const historyContext = this._historyContextProvider.getHistoryContext(docId);
778
795
  if (!historyContext) {
779
796
  logger.trace('no history context for speculative request');
@@ -782,20 +799,23 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
782
799
  // Create a speculative request
783
800
  // Use a dummy version since this is speculative and we don't have the actual post-edit version
784
801
  const logContext = new inlineEditLogContext_1.InlineEditRequestLogContext(docId.uri, 0, undefined);
785
- const req = new NextEditFetchRequest(`sp-${suggestion.source.opportunityId}`, logContext, undefined, `sp-${(0, uuid_1.generateUuid)()}`);
786
- logger.trace(`triggering speculative request for post-edit state (opportunityId=${req.opportunityId}, headerRequestId=${req.headerRequestId})`);
802
+ const req = new NextEditFetchRequest(`sp-${suggestion.source.opportunityId}`, logContext, undefined, true, `sp-${(0, uuid_1.generateUuid)()}`);
787
803
  logger.trace(`triggering speculative request for post-edit state (opportunityId=${req.opportunityId}, headerRequestId=${req.headerRequestId})`);
788
804
  try {
789
- const speculativeRequest = await this._createSpeculativeRequest(req, doc, shiftedSelection, historyContext, postEditContent, rootedEdit, result.edit, logger);
805
+ const speculativeRequest = await this._createSpeculativeRequest(req, doc, shiftedSelection, historyContext, postEditContent, rootedEdit, result.edit, {
806
+ triggeredBySpeculativeRequest: suggestion.source.isSpeculative,
807
+ isSubsequentEdit: suggestion.result?.isSubsequentEdit ?? false,
808
+ }, logger);
790
809
  if (speculativeRequest) {
791
810
  this._speculativePendingRequest = {
792
811
  request: speculativeRequest,
812
+ docId,
793
813
  postEditContent,
794
814
  };
795
815
  }
796
816
  }
797
817
  catch (e) {
798
- logger.trace(`speculative request failed: ${errors.toString(e)}`);
818
+ logger.trace(`speculative request failed: ${errors_1.ErrorUtils.toString(e)}`);
799
819
  }
800
820
  }
801
821
  /**
@@ -803,7 +823,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
803
823
  * The request will populate the cache so that when the user accepts the suggestion,
804
824
  * the next NES request can reuse or find the result in cache.
805
825
  */
806
- async _createSpeculativeRequest(req, doc, shiftedSelection, historyContext, postEditContent, rootedEdit, appliedEdit, parentLogger) {
826
+ async _createSpeculativeRequest(req, doc, shiftedSelection, historyContext, postEditContent, rootedEdit, appliedEdit, { triggeredBySpeculativeRequest, isSubsequentEdit }, parentLogger) {
807
827
  const logger = parentLogger.createSubLogger('_createSpeculativeRequest');
808
828
  const curDocId = doc.id;
809
829
  const recording = this._debugRecorder?.getRecentLog();
@@ -826,18 +846,11 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
826
846
  const workspaceRoot = this._workspace.getWorkspaceRoot(curDocId);
827
847
  const postEditEdit = new stringEdit_1.StringEdit([appliedEdit]);
828
848
  const postEditLineEdit = rootedLineEdit_1.RootedLineEdit.fromEdit(new edit_1.RootedEdit(doc.value.get(), postEditEdit)).removeCommonSuffixPrefixLines().edit;
829
- let selection = shiftedSelection;
830
- if (selection === undefined) {
831
- const appliedEditEndPos = postEditText.getTransformer().getPosition(appliedEdit.replaceRange.endExclusive + appliedEdit.getLengthDelta());
832
- const pos = new position_1.Position(appliedEditEndPos.lineNumber, 1);
833
- const offset = postEditText.getTransformer().getOffset(pos);
834
- selection = new offsetRange_1.OffsetRange(offset, offset);
835
- }
836
849
  const nextEditDoc = new statelessNextEditProvider_1.StatelessNextEditDocument(curDocId, workspaceRoot, docHist.languageId, doc.value.get().getLines(), // lines before the NES edit
837
850
  postEditLineEdit, // the NES edit as LineEdit
838
851
  doc.value.get(), // document before NES edit
839
852
  edit_1.Edits.single(postEditEdit), // the NES edit as Edits
840
- selection);
853
+ shiftedSelection);
841
854
  return {
842
855
  recentEdit: new edit_1.RootedEdit(doc.value.get(), postEditEdit),
843
856
  nextEditDoc,
@@ -849,9 +862,29 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
849
862
  const suggestedEdit = { kind: 'edit', docId: curDocId, edit: rootedEdit };
850
863
  xtabEditHistory.push(suggestedEdit);
851
864
  const firstEdit = new async_1.DeferredPromise();
852
- const nLinesEditWindow = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAutoExpandEditWindowLines, this._expService);
865
+ // FIXME@ulugbekna: implement advanced expansion
866
+ const autoExpandEditWindowLinesSetting = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSpeculativeRequestsAutoExpandEditWindowLines, this._expService);
867
+ let nLinesEditWindow;
868
+ switch (autoExpandEditWindowLinesSetting) {
869
+ case xtabPromptOptions_1.SpeculativeRequestsAutoExpandEditWindowLines.Off:
870
+ nLinesEditWindow = undefined;
871
+ break;
872
+ case xtabPromptOptions_1.SpeculativeRequestsAutoExpandEditWindowLines.Always:
873
+ nLinesEditWindow = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAutoExpandEditWindowLines, this._expService);
874
+ break;
875
+ case xtabPromptOptions_1.SpeculativeRequestsAutoExpandEditWindowLines.Smart: {
876
+ const isModelOnRightTrack = triggeredBySpeculativeRequest || isSubsequentEdit;
877
+ nLinesEditWindow = (isModelOnRightTrack
878
+ ? this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAutoExpandEditWindowLines, this._expService)
879
+ : undefined);
880
+ break;
881
+ }
882
+ default:
883
+ (0, assert_1.assertNever)(autoExpandEditWindowLinesSetting);
884
+ }
853
885
  const nextEditRequest = new statelessNextEditProvider_1.StatelessNextEditRequest(req.headerRequestId, req.opportunityId, postEditText, // documentBeforeEdits is the post-edit state
854
- projectedDocuments.map(d => d.nextEditDoc), activeDocAndIdx.idx, xtabEditHistory, firstEdit, nLinesEditWindow, logContext, undefined, // recordingBookmark
886
+ projectedDocuments.map(d => d.nextEditDoc), activeDocAndIdx.idx, xtabEditHistory, firstEdit, nLinesEditWindow, true, // isSpeculative
887
+ logContext, undefined, // recordingBookmark
855
888
  recording, undefined);
856
889
  logger.trace('starting speculative provider call');
857
890
  // Start the provider call - this runs in the background and populates the cache
@@ -868,7 +901,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
868
901
  const statePerDoc = new cache_1.CachedFunction((id) => {
869
902
  const doc = projectedDocuments.find(d => d.nextEditDoc.id === id);
870
903
  if (!doc) {
871
- throw new errors_1.BugIndicatingError();
904
+ throw new errors_2.BugIndicatingError();
872
905
  }
873
906
  return {
874
907
  docContents: doc.documentAfterEdits,
@@ -928,12 +961,23 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
928
961
  logger.trace(`speculative request completed with ${ithEdit + 1} edits`);
929
962
  }
930
963
  catch (e) {
931
- logger.trace(`speculative provider call error: ${errors.toString(e)}`);
964
+ logger.trace(`speculative provider call error: ${errors_1.ErrorUtils.toString(e)}`);
932
965
  }
933
966
  }
967
+ static shiftSelectionAfterEditWindow(postEditContentST, editWindowOffsetRange) {
968
+ const trans = postEditContentST.getTransformer();
969
+ const endOfEditWindow = trans.getPosition(editWindowOffsetRange.endExclusive - 1);
970
+ const shiftedCursorLineNumber = (endOfEditWindow.lineNumber + 1 < postEditContentST.lineRange.endLineNumberExclusive
971
+ ? endOfEditWindow.lineNumber + 1
972
+ : endOfEditWindow.lineNumber);
973
+ const shiftedSelectionCursorOffset = trans.getOffset(new position_1.Position(shiftedCursorLineNumber, 1));
974
+ const shiftedSelection = new offsetRange_1.OffsetRange(shiftedSelectionCursorOffset, shiftedSelectionCursorOffset);
975
+ return shiftedSelection;
976
+ }
934
977
  handleAcceptance(docId, suggestion) {
935
978
  this.runSnippy(docId, suggestion);
936
979
  this._statelessNextEditProvider.handleAcceptance?.();
980
+ this._lastOutcome = NesOutcome.Accepted;
937
981
  const logger = this._logger.createSubLogger(suggestion.source.opportunityId.substring(4, 8)).createSubLogger('handleAcceptance');
938
982
  if (suggestion === this._lastNextEditResult) {
939
983
  logger.trace('setting shouldExpandEditWindow to true due to acceptance of last suggestion');
@@ -945,6 +989,10 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
945
989
  }
946
990
  handleRejection(docId, suggestion) {
947
991
  (0, types_1.assertType)(suggestion.result, '@ulugbekna: undefined edit cannot be rejected?');
992
+ // The user rejected the suggestion, so the speculative request (which
993
+ // predicted the post-accept state) will never be reused. Cancel it to
994
+ // avoid wasting a server slot.
995
+ this._cancelSpeculativeRequest();
948
996
  const shownDuration = Date.now() - this._lastShownTime;
949
997
  if (shownDuration > 1000 && suggestion.result.edit) {
950
998
  // we can argue that the user had the time to review this
@@ -953,14 +1001,18 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
953
1001
  this._nextEditCache.rejectedNextEdit(suggestion.source.headerRequestId);
954
1002
  }
955
1003
  this._lastRejectionTime = Date.now();
1004
+ this._lastOutcome = NesOutcome.Rejected;
956
1005
  this._statelessNextEditProvider.handleRejection?.();
957
1006
  }
958
1007
  handleIgnored(docId, suggestion, supersededBy) {
1008
+ this._lastOutcome = NesOutcome.Ignored;
959
1009
  // Check if this was the last shown suggestion
960
1010
  const wasShown = this._lastShownSuggestionId === suggestion.requestId;
961
1011
  const wasSuperseded = supersededBy !== undefined;
962
1012
  if (wasShown && !wasSuperseded) {
963
- // Was shown to the user
1013
+ // The shown suggestion was dismissed (not superseded by a new one),
1014
+ // so the speculative request for its post-accept state is useless.
1015
+ this._cancelSpeculativeRequest();
964
1016
  this._statelessNextEditProvider.handleIgnored?.();
965
1017
  }
966
1018
  }
@@ -976,7 +1028,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
976
1028
  }
977
1029
  };
978
1030
  exports.NextEditProvider = NextEditProvider;
979
- exports.NextEditProvider = NextEditProvider = __decorate([
1031
+ exports.NextEditProvider = NextEditProvider = NextEditProvider_1 = __decorate([
980
1032
  __param(5, configurationService_1.IConfigurationService),
981
1033
  __param(6, snippyService_1.ISnippyService),
982
1034
  __param(7, logService_1.ILogService),
@@ -985,15 +1037,16 @@ exports.NextEditProvider = NextEditProvider = __decorate([
985
1037
  ], NextEditProvider);
986
1038
  function assertDefined(value) {
987
1039
  if (!value) {
988
- throw new errors_1.BugIndicatingError('expected value to be defined, but it was not');
1040
+ throw new errors_2.BugIndicatingError('expected value to be defined, but it was not');
989
1041
  }
990
1042
  return value;
991
1043
  }
992
1044
  class NextEditFetchRequest {
993
- constructor(opportunityId, log, providerRequestStartDateTime, headerRequestId = (0, uuid_1.generateUuid)()) {
1045
+ constructor(opportunityId, log, providerRequestStartDateTime, isSpeculative, headerRequestId = (0, uuid_1.generateUuid)()) {
994
1046
  this.opportunityId = opportunityId;
995
1047
  this.log = log;
996
1048
  this.providerRequestStartDateTime = providerRequestStartDateTime;
1049
+ this.isSpeculative = isSpeculative;
997
1050
  this.headerRequestId = headerRequestId;
998
1051
  }
999
1052
  }