@vscode/chat-lib 0.4.0 → 0.4.1-1

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 (279) hide show
  1. package/dist/src/_internal/extension/byok/node/openAIEndpoint.d.ts +1 -6
  2. package/dist/src/_internal/extension/byok/node/openAIEndpoint.d.ts.map +1 -1
  3. package/dist/src/_internal/extension/byok/node/openAIEndpoint.js +9 -20
  4. package/dist/src/_internal/extension/byok/node/openAIEndpoint.js.map +1 -1
  5. package/dist/src/_internal/extension/common/constants.d.ts +0 -1
  6. package/dist/src/_internal/extension/common/constants.d.ts.map +1 -1
  7. package/dist/src/_internal/extension/common/constants.js +2 -1
  8. package/dist/src/_internal/extension/common/constants.js.map +1 -1
  9. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.d.ts +4 -2
  10. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.d.ts.map +1 -1
  11. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.js +38 -5
  12. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.js.map +1 -1
  13. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/ghostText.d.ts +0 -1
  14. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/ghostText.d.ts.map +1 -1
  15. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/ghostText.js +17 -36
  16. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/ghostText.js.map +1 -1
  17. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.d.ts +1 -1
  18. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.d.ts.map +1 -1
  19. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.js +205 -122
  20. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.js.map +1 -1
  21. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/prompt/components/currentFile.d.ts.map +1 -1
  22. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/prompt/components/currentFile.js +15 -7
  23. package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/prompt/components/currentFile.js.map +1 -1
  24. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.d.ts +52 -8
  25. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.d.ts.map +1 -1
  26. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.js +208 -41
  27. package/dist/src/_internal/extension/inlineEdits/common/userInteractionMonitor.js.map +1 -1
  28. package/dist/src/_internal/extension/inlineEdits/node/nesConfigs.d.ts +1 -0
  29. package/dist/src/_internal/extension/inlineEdits/node/nesConfigs.d.ts.map +1 -1
  30. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts +14 -4
  31. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts.map +1 -1
  32. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.js +46 -30
  33. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.js.map +1 -1
  34. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts +24 -3
  35. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts.map +1 -1
  36. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js +472 -128
  37. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js.map +1 -1
  38. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.d.ts.map +1 -1
  39. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js +8 -2
  40. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js.map +1 -1
  41. package/dist/src/_internal/extension/inlineEdits/node/nextEditResult.d.ts +0 -4
  42. package/dist/src/_internal/extension/inlineEdits/node/nextEditResult.d.ts.map +1 -1
  43. package/dist/src/_internal/extension/inlineEdits/node/nextEditResult.js.map +1 -1
  44. package/dist/src/_internal/extension/power/common/powerService.d.ts +33 -0
  45. package/dist/src/_internal/extension/power/common/powerService.d.ts.map +1 -0
  46. package/dist/src/_internal/extension/power/common/powerService.js +25 -0
  47. package/dist/src/_internal/extension/power/common/powerService.js.map +1 -0
  48. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts +6 -2
  49. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts.map +1 -1
  50. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js +124 -13
  51. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js.map +1 -1
  52. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.d.ts +23 -3
  53. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.d.ts.map +1 -1
  54. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.js +21 -9
  55. package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.js.map +1 -1
  56. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.d.ts +6 -0
  57. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.d.ts.map +1 -0
  58. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.js +89 -0
  59. package/dist/src/_internal/extension/xtab/common/diffHistoryForPrompt.js.map +1 -0
  60. package/dist/src/_internal/extension/xtab/common/inlineSuggestion.d.ts +15 -0
  61. package/dist/src/_internal/extension/xtab/common/inlineSuggestion.d.ts.map +1 -0
  62. package/dist/src/_internal/extension/xtab/common/inlineSuggestion.js +43 -0
  63. package/dist/src/_internal/extension/xtab/common/inlineSuggestion.js.map +1 -0
  64. package/dist/src/_internal/extension/xtab/common/lintErrors.d.ts +4 -4
  65. package/dist/src/_internal/extension/xtab/common/lintErrors.d.ts.map +1 -1
  66. package/dist/src/_internal/extension/xtab/common/lintErrors.js +70 -26
  67. package/dist/src/_internal/extension/xtab/common/lintErrors.js.map +1 -1
  68. package/dist/src/_internal/extension/xtab/common/promptCrafting.d.ts +13022 -364
  69. package/dist/src/_internal/extension/xtab/common/promptCrafting.d.ts.map +1 -1
  70. package/dist/src/_internal/extension/xtab/common/promptCrafting.js +14 -233
  71. package/dist/src/_internal/extension/xtab/common/promptCrafting.js.map +1 -1
  72. package/dist/src/_internal/extension/xtab/common/promptCraftingUtils.d.ts +4 -0
  73. package/dist/src/_internal/extension/xtab/common/promptCraftingUtils.d.ts.map +1 -0
  74. package/dist/src/_internal/extension/xtab/common/promptCraftingUtils.js +22 -0
  75. package/dist/src/_internal/extension/xtab/common/promptCraftingUtils.js.map +1 -0
  76. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.d.ts +41 -0
  77. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.d.ts.map +1 -0
  78. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.js +375 -0
  79. package/dist/src/_internal/extension/xtab/common/recentFilesForPrompt.js.map +1 -0
  80. package/dist/src/_internal/extension/xtab/common/terminalOutput.d.ts +20 -0
  81. package/dist/src/_internal/extension/xtab/common/terminalOutput.d.ts.map +1 -0
  82. package/dist/src/_internal/extension/xtab/common/terminalOutput.js +105 -0
  83. package/dist/src/_internal/extension/xtab/common/terminalOutput.js.map +1 -0
  84. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.d.ts +2 -3
  85. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.d.ts.map +1 -1
  86. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js +2 -1
  87. package/dist/src/_internal/extension/xtab/node/xtabCustomDiffPatchResponseHandler.js.map +1 -1
  88. package/dist/src/_internal/extension/xtab/node/xtabEndpoint.d.ts.map +1 -1
  89. package/dist/src/_internal/extension/xtab/node/xtabEndpoint.js +1 -1
  90. package/dist/src/_internal/extension/xtab/node/xtabEndpoint.js.map +1 -1
  91. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.d.ts.map +1 -1
  92. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js +2 -1
  93. package/dist/src/_internal/extension/xtab/node/xtabNextCursorPredictor.js.map +1 -1
  94. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts +52 -9
  95. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts.map +1 -1
  96. package/dist/src/_internal/extension/xtab/node/xtabProvider.js +370 -158
  97. package/dist/src/_internal/extension/xtab/node/xtabProvider.js.map +1 -1
  98. package/dist/src/_internal/extension/xtab/node/xtabUtils.d.ts +1 -7
  99. package/dist/src/_internal/extension/xtab/node/xtabUtils.d.ts.map +1 -1
  100. package/dist/src/_internal/extension/xtab/node/xtabUtils.js +21 -40
  101. package/dist/src/_internal/extension/xtab/node/xtabUtils.js.map +1 -1
  102. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.js +1 -1
  103. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.js.map +1 -1
  104. package/dist/src/_internal/platform/chat/common/commonTypes.d.ts +2 -2
  105. package/dist/src/_internal/platform/chat/common/commonTypes.d.ts.map +1 -1
  106. package/dist/src/_internal/platform/chat/common/commonTypes.js +8 -8
  107. package/dist/src/_internal/platform/chat/common/commonTypes.js.map +1 -1
  108. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts +46 -17
  109. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts.map +1 -1
  110. package/dist/src/_internal/platform/configuration/common/configurationService.js +48 -13
  111. package/dist/src/_internal/platform/configuration/common/configurationService.js.map +1 -1
  112. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts +1 -1
  113. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts.map +1 -1
  114. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js +5 -10
  115. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js.map +1 -1
  116. package/dist/src/_internal/platform/endpoint/common/compactionDataContainer.d.ts +17 -0
  117. package/dist/src/_internal/platform/endpoint/common/compactionDataContainer.d.ts.map +1 -0
  118. package/dist/src/_internal/platform/endpoint/common/compactionDataContainer.js +37 -0
  119. package/dist/src/_internal/platform/endpoint/common/compactionDataContainer.js.map +1 -0
  120. package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts +9 -5
  121. package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts.map +1 -1
  122. package/dist/src/_internal/platform/endpoint/common/endpointProvider.js.map +1 -1
  123. package/dist/src/_internal/platform/endpoint/node/autoChatEndpoint.js +1 -1
  124. package/dist/src/_internal/platform/endpoint/node/autoChatEndpoint.js.map +1 -1
  125. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts +4 -11
  126. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts.map +1 -1
  127. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js +15 -54
  128. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js.map +1 -1
  129. package/dist/src/_internal/platform/endpoint/node/copilotChatEndpoint.d.ts.map +1 -1
  130. package/dist/src/_internal/platform/endpoint/node/copilotChatEndpoint.js +1 -1
  131. package/dist/src/_internal/platform/endpoint/node/copilotChatEndpoint.js.map +1 -1
  132. package/dist/src/_internal/platform/endpoint/node/messagesApi.d.ts.map +1 -1
  133. package/dist/src/_internal/platform/endpoint/node/messagesApi.js +68 -25
  134. package/dist/src/_internal/platform/endpoint/node/messagesApi.js.map +1 -1
  135. package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts.map +1 -1
  136. package/dist/src/_internal/platform/endpoint/node/responsesApi.js +72 -2
  137. package/dist/src/_internal/platform/endpoint/node/responsesApi.js.map +1 -1
  138. package/dist/src/_internal/platform/env/common/envService.d.ts +6 -0
  139. package/dist/src/_internal/platform/env/common/envService.d.ts.map +1 -1
  140. package/dist/src/_internal/platform/env/common/envService.js.map +1 -1
  141. package/dist/src/_internal/platform/env/common/nullEnvService.d.ts +3 -0
  142. package/dist/src/_internal/platform/env/common/nullEnvService.d.ts.map +1 -1
  143. package/dist/src/_internal/platform/env/common/nullEnvService.js +4 -0
  144. package/dist/src/_internal/platform/env/common/nullEnvService.js.map +1 -1
  145. package/dist/src/_internal/platform/github/common/githubAPI.d.ts +1 -1
  146. package/dist/src/_internal/platform/github/common/githubAPI.d.ts.map +1 -1
  147. package/dist/src/_internal/platform/github/common/githubAPI.js +4 -2
  148. package/dist/src/_internal/platform/github/common/githubAPI.js.map +1 -1
  149. package/dist/src/_internal/platform/github/common/githubService.d.ts +4 -1
  150. package/dist/src/_internal/platform/github/common/githubService.d.ts.map +1 -1
  151. package/dist/src/_internal/platform/github/common/githubService.js +3 -3
  152. package/dist/src/_internal/platform/github/common/githubService.js.map +1 -1
  153. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabHistoryOptions.d.ts +9 -0
  154. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabHistoryOptions.d.ts.map +1 -0
  155. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabHistoryOptions.js +18 -0
  156. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabHistoryOptions.js.map +1 -0
  157. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.d.ts +103 -2
  158. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.d.ts.map +1 -1
  159. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.js +231 -1
  160. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.js.map +1 -1
  161. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts +11 -5
  162. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts.map +1 -1
  163. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js +33 -18
  164. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js.map +1 -1
  165. package/dist/src/_internal/platform/inlineEdits/common/inlineEditsModelService.d.ts +2 -0
  166. package/dist/src/_internal/platform/inlineEdits/common/inlineEditsModelService.d.ts.map +1 -1
  167. package/dist/src/_internal/platform/inlineEdits/common/inlineEditsModelService.js +4 -0
  168. package/dist/src/_internal/platform/inlineEdits/common/inlineEditsModelService.js.map +1 -1
  169. package/dist/src/_internal/platform/inlineEdits/common/responseProcessor.d.ts +1 -2
  170. package/dist/src/_internal/platform/inlineEdits/common/responseProcessor.d.ts.map +1 -1
  171. package/dist/src/_internal/platform/inlineEdits/common/responseProcessor.js +13 -0
  172. package/dist/src/_internal/platform/inlineEdits/common/responseProcessor.js.map +1 -1
  173. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts +37 -10
  174. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts.map +1 -1
  175. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js +43 -6
  176. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js.map +1 -1
  177. package/dist/src/_internal/platform/inlineEdits/common/workspaceEditTracker/nesXtabHistoryTracker.d.ts +41 -2
  178. package/dist/src/_internal/platform/inlineEdits/common/workspaceEditTracker/nesXtabHistoryTracker.d.ts.map +1 -1
  179. package/dist/src/_internal/platform/inlineEdits/common/workspaceEditTracker/nesXtabHistoryTracker.js +90 -8
  180. package/dist/src/_internal/platform/inlineEdits/common/workspaceEditTracker/nesXtabHistoryTracker.js.map +1 -1
  181. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.d.ts +9 -2
  182. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.d.ts.map +1 -1
  183. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.js +65 -54
  184. package/dist/src/_internal/platform/inlineEdits/node/inlineEditsModelService.js.map +1 -1
  185. package/dist/src/_internal/platform/log/common/logService.d.ts +30 -0
  186. package/dist/src/_internal/platform/log/common/logService.d.ts.map +1 -1
  187. package/dist/src/_internal/platform/log/common/logService.js.map +1 -1
  188. package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.d.ts +5 -1
  189. package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.d.ts.map +1 -1
  190. package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.js +121 -6
  191. package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.js.map +1 -1
  192. package/dist/src/_internal/platform/nesFetch/node/streamTransformer.d.ts +1 -4
  193. package/dist/src/_internal/platform/nesFetch/node/streamTransformer.d.ts.map +1 -1
  194. package/dist/src/_internal/platform/nesFetch/node/streamTransformer.js +1 -21
  195. package/dist/src/_internal/platform/nesFetch/node/streamTransformer.js.map +1 -1
  196. package/dist/src/_internal/platform/networking/common/anthropic.d.ts +11 -16
  197. package/dist/src/_internal/platform/networking/common/anthropic.d.ts.map +1 -1
  198. package/dist/src/_internal/platform/networking/common/anthropic.js +37 -39
  199. package/dist/src/_internal/platform/networking/common/anthropic.js.map +1 -1
  200. package/dist/src/_internal/platform/networking/common/fetch.d.ts +4 -2
  201. package/dist/src/_internal/platform/networking/common/fetch.d.ts.map +1 -1
  202. package/dist/src/_internal/platform/networking/common/fetch.js +9 -0
  203. package/dist/src/_internal/platform/networking/common/fetch.js.map +1 -1
  204. package/dist/src/_internal/platform/networking/common/fetcherService.d.ts +1 -0
  205. package/dist/src/_internal/platform/networking/common/fetcherService.d.ts.map +1 -1
  206. package/dist/src/_internal/platform/networking/common/fetcherService.js.map +1 -1
  207. package/dist/src/_internal/platform/networking/common/networking.d.ts +14 -12
  208. package/dist/src/_internal/platform/networking/common/networking.d.ts.map +1 -1
  209. package/dist/src/_internal/platform/networking/common/networking.js +1 -0
  210. package/dist/src/_internal/platform/networking/common/networking.js.map +1 -1
  211. package/dist/src/_internal/platform/networking/common/openai.d.ts +11 -0
  212. package/dist/src/_internal/platform/networking/common/openai.d.ts.map +1 -1
  213. package/dist/src/_internal/platform/networking/common/openai.js +3 -1
  214. package/dist/src/_internal/platform/networking/common/openai.js.map +1 -1
  215. package/dist/src/_internal/platform/requestLogger/common/capturingToken.d.ts +35 -1
  216. package/dist/src/_internal/platform/requestLogger/common/capturingToken.d.ts.map +1 -1
  217. package/dist/src/_internal/platform/requestLogger/common/capturingToken.js +21 -1
  218. package/dist/src/_internal/platform/requestLogger/common/capturingToken.js.map +1 -1
  219. package/dist/src/_internal/platform/requestLogger/node/requestLogger.d.ts +35 -0
  220. package/dist/src/_internal/platform/requestLogger/node/requestLogger.d.ts.map +1 -1
  221. package/dist/src/_internal/platform/requestLogger/node/requestLogger.js +54 -1
  222. package/dist/src/_internal/platform/requestLogger/node/requestLogger.js.map +1 -1
  223. package/dist/src/_internal/platform/telemetry/common/telemetry.d.ts +2 -0
  224. package/dist/src/_internal/platform/telemetry/common/telemetry.d.ts.map +1 -1
  225. package/dist/src/_internal/platform/telemetry/common/telemetry.js +1 -0
  226. package/dist/src/_internal/platform/telemetry/common/telemetry.js.map +1 -1
  227. package/dist/src/_internal/platform/telemetry/common/telemetryData.d.ts.map +1 -1
  228. package/dist/src/_internal/platform/telemetry/common/telemetryData.js +3 -0
  229. package/dist/src/_internal/platform/telemetry/common/telemetryData.js.map +1 -1
  230. package/dist/src/_internal/platform/terminal/common/terminalService.d.ts +111 -0
  231. package/dist/src/_internal/platform/terminal/common/terminalService.d.ts.map +1 -0
  232. package/dist/src/_internal/platform/terminal/common/terminalService.js +83 -0
  233. package/dist/src/_internal/platform/terminal/common/terminalService.js.map +1 -0
  234. package/dist/src/_internal/util/common/arrays.d.ts +5 -0
  235. package/dist/src/_internal/util/common/arrays.d.ts.map +1 -1
  236. package/dist/src/_internal/util/common/arrays.js +10 -0
  237. package/dist/src/_internal/util/common/arrays.js.map +1 -1
  238. package/dist/src/_internal/util/common/asyncIterableUtils.d.ts +17 -0
  239. package/dist/src/_internal/util/common/asyncIterableUtils.d.ts.map +1 -0
  240. package/dist/src/_internal/util/common/asyncIterableUtils.js +94 -0
  241. package/dist/src/_internal/util/common/asyncIterableUtils.js.map +1 -0
  242. package/dist/src/_internal/util/common/result.d.ts +34 -10
  243. package/dist/src/_internal/util/common/result.d.ts.map +1 -1
  244. package/dist/src/_internal/util/common/result.js +91 -2
  245. package/dist/src/_internal/util/common/result.js.map +1 -1
  246. package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts +15 -3
  247. package/dist/src/_internal/util/common/test/shims/chatTypes.d.ts.map +1 -1
  248. package/dist/src/_internal/util/common/test/shims/chatTypes.js +26 -4
  249. package/dist/src/_internal/util/common/test/shims/chatTypes.js.map +1 -1
  250. package/dist/src/_internal/util/common/test/shims/themes.d.ts +13 -0
  251. package/dist/src/_internal/util/common/test/shims/themes.d.ts.map +1 -0
  252. package/dist/src/_internal/util/common/test/shims/themes.js +27 -0
  253. package/dist/src/_internal/util/common/test/shims/themes.js.map +1 -0
  254. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.d.ts.map +1 -1
  255. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js +4 -1
  256. package/dist/src/_internal/util/common/test/shims/vscodeTypesShim.js.map +1 -1
  257. package/dist/src/_internal/util/vs/base/common/codicons.d.ts +2 -0
  258. package/dist/src/_internal/util/vs/base/common/codicons.d.ts.map +1 -1
  259. package/dist/src/_internal/util/vs/base/common/codiconsLibrary.d.ts +2 -0
  260. package/dist/src/_internal/util/vs/base/common/codiconsLibrary.d.ts.map +1 -1
  261. package/dist/src/_internal/util/vs/base/common/codiconsLibrary.js +2 -0
  262. package/dist/src/_internal/util/vs/base/common/codiconsLibrary.js.map +1 -1
  263. package/dist/src/_internal/util/vs/base/common/mime.d.ts.map +1 -1
  264. package/dist/src/_internal/util/vs/base/common/mime.js +7 -5
  265. package/dist/src/_internal/util/vs/base/common/mime.js.map +1 -1
  266. package/dist/src/_internal/util/vs/editor/common/core/ranges/offsetRange.d.ts +4 -0
  267. package/dist/src/_internal/util/vs/editor/common/core/ranges/offsetRange.d.ts.map +1 -1
  268. package/dist/src/_internal/util/vs/editor/common/core/ranges/offsetRange.js +4 -0
  269. package/dist/src/_internal/util/vs/editor/common/core/ranges/offsetRange.js.map +1 -1
  270. package/dist/src/_internal/vscodeTypes.d.ts +2 -0
  271. package/dist/src/_internal/vscodeTypes.d.ts.map +1 -1
  272. package/dist/src/_internal/vscodeTypes.js +4 -2
  273. package/dist/src/_internal/vscodeTypes.js.map +1 -1
  274. package/dist/src/main.d.ts +4 -1
  275. package/dist/src/main.d.ts.map +1 -1
  276. package/dist/src/main.js +10 -1
  277. package/dist/src/main.js.map +1 -1
  278. package/dist/src/package.json +493 -250
  279. package/package.json +2 -2
@@ -47,12 +47,17 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
47
47
  };
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
49
  exports.NextEditFetchRequest = exports.NextEditProvider = void 0;
50
+ const path_1 = require("path");
50
51
  const configurationService_1 = require("../../../platform/configuration/common/configurationService");
51
52
  const edit_1 = require("../../../platform/inlineEdits/common/dataTypes/edit");
52
53
  const rootedLineEdit_1 = require("../../../platform/inlineEdits/common/dataTypes/rootedLineEdit");
54
+ const xtabPromptOptions_1 = require("../../../platform/inlineEdits/common/dataTypes/xtabPromptOptions");
55
+ const inlineEditLogContext_1 = require("../../../platform/inlineEdits/common/inlineEditLogContext");
53
56
  const statelessNextEditProvider_1 = require("../../../platform/inlineEdits/common/statelessNextEditProvider");
54
57
  const observable_1 = require("../../../platform/inlineEdits/common/utils/observable");
55
58
  const logService_1 = require("../../../platform/log/common/logService");
59
+ const capturingToken_1 = require("../../../platform/requestLogger/common/capturingToken");
60
+ const requestLogger_1 = require("../../../platform/requestLogger/node/requestLogger");
56
61
  const snippyService_1 = require("../../../platform/snippy/common/snippyService");
57
62
  const nullExperimentationService_1 = require("../../../platform/telemetry/common/nullExperimentationService");
58
63
  const errors = __importStar(require("../../../util/common/errors"));
@@ -68,11 +73,40 @@ const types_1 = require("../../../util/vs/base/common/types");
68
73
  const uuid_1 = require("../../../util/vs/base/common/uuid");
69
74
  const lineEdit_1 = require("../../../util/vs/editor/common/core/edits/lineEdit");
70
75
  const stringEdit_1 = require("../../../util/vs/editor/common/core/edits/stringEdit");
76
+ const position_1 = require("../../../util/vs/editor/common/core/position");
71
77
  const offsetRange_1 = require("../../../util/vs/editor/common/core/ranges/offsetRange");
78
+ const abstractText_1 = require("../../../util/vs/editor/common/core/text/abstractText");
72
79
  const editRebase_1 = require("../common/editRebase");
73
80
  const rejectionCollector_1 = require("../common/rejectionCollector");
74
81
  const nextEditCache_1 = require("./nextEditCache");
75
82
  const nextEditResult_1 = require("./nextEditResult");
83
+ /**
84
+ * Computes a reduced window range that encompasses both the original window (shrunk by one line
85
+ * on each end) and the full line where the cursor is located.
86
+ *
87
+ * This ensures the cache invalidation window always includes the cursor's line while trimming
88
+ * the edges of the original window.
89
+ */
90
+ function computeReducedWindow(window, activeDocSelection, documentBeforeEdits) {
91
+ if (!activeDocSelection) {
92
+ return window;
93
+ }
94
+ const cursorOffset = activeDocSelection.endExclusive;
95
+ const t = documentBeforeEdits.getTransformer();
96
+ const cursorPosition = t.getPosition(cursorOffset);
97
+ const lineOffset = t.getOffset(cursorPosition.with(undefined, 1));
98
+ const lineEndOffset = t.getOffset(cursorPosition.with(undefined, t.getLineLength(cursorPosition.lineNumber) + 1));
99
+ const reducedOffset = t.getOffset(t.getPosition(window.start).delta(1));
100
+ const reducedEndPosition = t.getPosition(window.endExclusive).delta(-2);
101
+ const reducedEndOffset = t.getOffset(reducedEndPosition.column > 1 ? reducedEndPosition.with(undefined, t.getLineLength(reducedEndPosition.lineNumber) + 1) : reducedEndPosition);
102
+ return new offsetRange_1.OffsetRange(Math.min(reducedOffset, lineOffset), Math.max(reducedEndOffset, lineEndOffset));
103
+ }
104
+ function convertLineEditToEdit(nextLineEdit, projectedDocuments, docId) {
105
+ const doc = projectedDocuments.find(d => d.nextEditDoc.id === docId);
106
+ const rootedLineEdit = new rootedLineEdit_1.RootedLineEdit(doc.documentAfterEdits, nextLineEdit);
107
+ const suggestedEdit = rootedLineEdit.toEdit();
108
+ return suggestedEdit;
109
+ }
76
110
  let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
77
111
  get lastRejectionTime() {
78
112
  return this._lastRejectionTime;
@@ -80,7 +114,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
80
114
  get lastTriggerTime() {
81
115
  return this._lastTriggerTime;
82
116
  }
83
- constructor(_workspace, _statelessNextEditProvider, _historyContextProvider, _xtabHistoryTracker, _debugRecorder, _configService, _snippyService, _logService, _expService) {
117
+ constructor(_workspace, _statelessNextEditProvider, _historyContextProvider, _xtabHistoryTracker, _debugRecorder, _configService, _snippyService, _logService, _expService, _requestLogger) {
84
118
  super();
85
119
  this._workspace = _workspace;
86
120
  this._statelessNextEditProvider = _statelessNextEditProvider;
@@ -91,10 +125,19 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
91
125
  this._snippyService = _snippyService;
92
126
  this._logService = _logService;
93
127
  this._expService = _expService;
128
+ this._requestLogger = _requestLogger;
94
129
  this.ID = this._statelessNextEditProvider.ID;
95
130
  this._rejectionCollector = this._register(new rejectionCollector_1.RejectionCollector(this._workspace, this._logService));
96
131
  this._pendingStatelessNextEditRequest = null;
132
+ /**
133
+ * Tracks a speculative request for the post-edit document state.
134
+ * When a suggestion is shown, we speculatively fetch the next edit as if the user had already accepted.
135
+ * This allows reusing the in-flight request when the user actually accepts the suggestion.
136
+ */
137
+ this._speculativePendingRequest = null;
97
138
  this._lastShownTime = 0;
139
+ /** The requestId of the last shown suggestion. We store only the requestId (not the object) to avoid preventing garbage collection. */
140
+ this._lastShownSuggestionId = undefined;
98
141
  this._lastRejectionTime = 0;
99
142
  this._lastTriggerTime = 0;
100
143
  this._shouldExpandEditWindow = false;
@@ -152,7 +195,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
152
195
  const documentAtInvocationTime = doc.value.get();
153
196
  const selections = doc.selection.get();
154
197
  const nesConfigs = this.determineNesConfigs(telemetryBuilder, logContext);
155
- const cachedEdit = this._nextEditCache.lookupNextEdit(docId, documentAtInvocationTime, selections, nesConfigs);
198
+ const cachedEdit = this._nextEditCache.lookupNextEdit(docId, documentAtInvocationTime, selections);
156
199
  if (cachedEdit?.rejected) {
157
200
  logger.trace('cached edit was previously rejected');
158
201
  telemetryBuilder.setStatus('previouslyRejectedCache');
@@ -251,7 +294,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
251
294
  telemetryBuilder.setStatus(`noEdit:gotCancelled`);
252
295
  return emptyResult;
253
296
  }
254
- if (this._rejectionCollector.isRejected(targetDocumentId, edit.actualEdit) || currentDocument && this._nextEditCache.isRejectedNextEdit(targetDocumentId, currentDocument, edit.actualEdit, nesConfigs)) {
297
+ if (this._rejectionCollector.isRejected(targetDocumentId, edit.actualEdit) || currentDocument && this._nextEditCache.isRejectedNextEdit(targetDocumentId, currentDocument, edit.actualEdit)) {
255
298
  logger.trace('edit was previously rejected');
256
299
  telemetryBuilder.setStatus('previouslyRejected');
257
300
  telemetryBuilder.setWasPreviouslyRejected();
@@ -260,8 +303,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
260
303
  logContext.setResult(rootedLineEdit_1.RootedLineEdit.fromEdit(new edit_1.RootedEdit(documentAtInvocationTime, new stringEdit_1.StringEdit([edit.actualEdit]))));
261
304
  (0, assert_1.assert)(currentDocument !== undefined, 'should be defined if edit is defined');
262
305
  telemetryBuilder.setStatus('notAccepted'); // Acceptance pending.
263
- const showRangePreference = this._statelessNextEditProvider.showNextEditPreference ?? "aroundEdit" /* ShowNextEditPreference.AroundEdit */;
264
- const nextEditResult = new nextEditResult_1.NextEditResult(logContext.requestId, req, { edit: edit.actualEdit, isFromCursorJump: edit.isFromCursorJump, showRangePreference, documentBeforeEdits: currentDocument, targetDocumentId });
306
+ const nextEditResult = new nextEditResult_1.NextEditResult(logContext.requestId, req, { edit: edit.actualEdit, isFromCursorJump: edit.isFromCursorJump, documentBeforeEdits: currentDocument, targetDocumentId });
265
307
  telemetryBuilder.setHasNextEdit(true);
266
308
  const delay = this.computeMinimumResponseDelay({ triggerTime, isRebasedCachedEdit, isSubsequentCachedEdit, enforceCacheDelay: context.enforceCacheDelay }, logger);
267
309
  if (delay > 0) {
@@ -278,6 +320,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
278
320
  determineNesConfigs(telemetryBuilder, logContext) {
279
321
  const nesConfigs = {
280
322
  isAsyncCompletions: this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAsyncCompletions, this._expService),
323
+ isEagerBackupRequest: this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsEagerBackupRequest, this._expService),
281
324
  };
282
325
  telemetryBuilder.setNESConfigs({ ...nesConfigs });
283
326
  logContext.addCodeblockToLog(JSON.stringify(nesConfigs, null, '\t'));
@@ -308,21 +351,75 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
308
351
  const selectionAtInvocationTime = doc.selection.get();
309
352
  const logContext = req.log;
310
353
  logContext.setRecentEdit(historyContext);
354
+ // Check if we can reuse the regular pending request
311
355
  const pendingRequestStillCurrent = documentAtInvocationTime.value === this._pendingStatelessNextEditRequest?.documentBeforeEdits.value;
312
356
  const existingNextEditRequest = (pendingRequestStillCurrent || nesConfigs.isAsyncCompletions) && !this._pendingStatelessNextEditRequest?.cancellationTokenSource.token.isCancellationRequested
313
357
  && this._pendingStatelessNextEditRequest || undefined;
314
- if (existingNextEditRequest) {
358
+ // Check if we can reuse the speculative pending request (from when a suggestion was shown)
359
+ const speculativeRequestMatches = this._speculativePendingRequest?.postEditContent === documentAtInvocationTime.value
360
+ && !this._speculativePendingRequest.request.cancellationTokenSource.token.isCancellationRequested;
361
+ const speculativeRequest = speculativeRequestMatches ? this._speculativePendingRequest?.request : undefined;
362
+ // Prefer speculative request if it matches (it was specifically created for this post-edit state)
363
+ const requestToReuse = speculativeRequest ?? existingNextEditRequest;
364
+ if (requestToReuse) {
315
365
  // Nice! No need to make another request, we can reuse the result from a pending request.
316
- const nextEditResult = await this._joinNextEditRequest(existingNextEditRequest, telemetryBuilder, logContext, cancellationToken);
317
- if (pendingRequestStillCurrent) {
366
+ if (speculativeRequest) {
367
+ logger.trace(`reusing speculative pending request (opportunityId=${speculativeRequest.opportunityId}, headerRequestId=${speculativeRequest.headerRequestId})`);
368
+ // Clear the speculative request since we're using it
369
+ this._speculativePendingRequest = null;
370
+ }
371
+ const requestStillCurrent = speculativeRequest
372
+ ? speculativeRequestMatches // For speculative, we already checked it matches
373
+ : pendingRequestStillCurrent;
374
+ if (requestStillCurrent) {
375
+ const nextEditResult = await this._joinNextEditRequest(requestToReuse, telemetryBuilder, logContext, cancellationToken);
318
376
  telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
319
- return nextEditResult.nextEdit.isError() ? nextEditResult.nextEdit : existingNextEditRequest.firstEdit.p;
377
+ return nextEditResult.nextEdit.isError() ? nextEditResult.nextEdit : requestToReuse.firstEdit.p;
378
+ }
379
+ else if (nesConfigs.isEagerBackupRequest) {
380
+ // The pending request is stale (document diverged). Start a backup request
381
+ // in parallel so that if rebase fails, we already have a head start.
382
+ logger.trace('starting eager backup request in parallel with rebase attempt');
383
+ // _executeNewNextEditRequest cancels the current _pendingStatelessNextEditRequest,
384
+ // but we're still trying to join+rebase requestToReuse. Temporarily clear the
385
+ // pending field so the stale request isn't cancelled prematurely.
386
+ this._pendingStatelessNextEditRequest = null;
387
+ const backupPromise = this._executeNewNextEditRequest(req, doc, historyContext, nesConfigs, shouldExpandEditWindow, logger, telemetryBuilder, cancellationToken);
388
+ const cancelBackupRequest = () => {
389
+ void backupPromise
390
+ .then(r => r.nextEditRequest.cancellationTokenSource.cancel())
391
+ .catch(() => undefined);
392
+ };
393
+ // Simultaneously attempt to join + rebase the stale request
394
+ const nextEditResult = await this._joinNextEditRequest(requestToReuse, telemetryBuilder, logContext, cancellationToken);
395
+ const cacheResult = await requestToReuse.firstEdit.p;
396
+ if (cacheResult.isOk() && cacheResult.val.edit) {
397
+ const rebasedCachedEdit = this._nextEditCache.tryRebaseCacheEntry(cacheResult.val, documentAtInvocationTime, selectionAtInvocationTime);
398
+ if (rebasedCachedEdit) {
399
+ logger.trace('rebase succeeded, cancelling eager backup request');
400
+ cancelBackupRequest();
401
+ telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
402
+ return result_1.Result.ok(rebasedCachedEdit);
403
+ }
404
+ }
405
+ if (cancellationToken.isCancellationRequested) {
406
+ logger.trace('cancelled after rebase failed (eager backup path)');
407
+ cancelBackupRequest();
408
+ telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
409
+ return result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterFailedRebase'));
410
+ }
411
+ // Rebase failed — use the backup request that's already been running in parallel
412
+ logger.trace('rebase failed, using eager backup request');
413
+ const backupRes = await backupPromise;
414
+ telemetryBuilder.setStatelessNextEditTelemetry(backupRes.nextEditResult.telemetry);
415
+ return backupRes.nextEditResult.nextEdit.isError() ? backupRes.nextEditResult.nextEdit : backupRes.nextEditRequest.firstEdit.p;
320
416
  }
321
417
  else {
418
+ const nextEditResult = await this._joinNextEditRequest(requestToReuse, telemetryBuilder, logContext, cancellationToken);
322
419
  // Needs rebasing.
323
- const cacheResult = await existingNextEditRequest.firstEdit.p;
420
+ const cacheResult = await requestToReuse.firstEdit.p;
324
421
  if (cacheResult.isOk() && cacheResult.val.edit) {
325
- const rebasedCachedEdit = this._nextEditCache.tryRebaseCacheEntry(cacheResult.val, documentAtInvocationTime, selectionAtInvocationTime, nesConfigs);
422
+ const rebasedCachedEdit = this._nextEditCache.tryRebaseCacheEntry(cacheResult.val, documentAtInvocationTime, selectionAtInvocationTime);
326
423
  if (rebasedCachedEdit) {
327
424
  telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
328
425
  return result_1.Result.ok(rebasedCachedEdit);
@@ -334,14 +431,14 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
334
431
  return result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterFailedRebase'));
335
432
  }
336
433
  // Rebase failed (or result had error). Check if there is a new pending request. Otherwise continue with a new request below.
337
- const pendingRequestStillCurrent = documentAtInvocationTime.value === this._pendingStatelessNextEditRequest?.documentBeforeEdits.value;
338
- const existingNextEditRequest2 = pendingRequestStillCurrent && !this._pendingStatelessNextEditRequest?.cancellationTokenSource.token.isCancellationRequested
434
+ const pendingRequestStillCurrent2 = documentAtInvocationTime.value === this._pendingStatelessNextEditRequest?.documentBeforeEdits.value;
435
+ const existingNextEditRequest2 = pendingRequestStillCurrent2 && !this._pendingStatelessNextEditRequest?.cancellationTokenSource.token.isCancellationRequested
339
436
  && this._pendingStatelessNextEditRequest || undefined;
340
437
  if (existingNextEditRequest2) {
341
438
  logger.trace('reusing 2nd existing next edit request after rebase failed');
342
- const nextEditResult = await this._joinNextEditRequest(existingNextEditRequest2, telemetryBuilder, logContext, cancellationToken);
343
- telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult.telemetry);
344
- return nextEditResult.nextEdit.isError() ? nextEditResult.nextEdit : existingNextEditRequest2.firstEdit.p;
439
+ const nextEditResult2 = await this._joinNextEditRequest(existingNextEditRequest2, telemetryBuilder, logContext, cancellationToken);
440
+ telemetryBuilder.setStatelessNextEditTelemetry(nextEditResult2.telemetry);
441
+ return nextEditResult2.nextEdit.isError() ? nextEditResult2.nextEdit : existingNextEditRequest2.firstEdit.p;
345
442
  }
346
443
  logger.trace('creating new next edit request after rebase failed');
347
444
  }
@@ -354,7 +451,7 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
354
451
  }
355
452
  async _joinNextEditRequest(nextEditRequest, telemetryBuilder, logContext, cancellationToken) {
356
453
  // TODO: Will the telemetry look alright in this case?
357
- telemetryBuilder.setHeaderRequestId(nextEditRequest.id);
454
+ telemetryBuilder.setHeaderRequestId(nextEditRequest.headerRequestId);
358
455
  telemetryBuilder.setIsFromCache();
359
456
  telemetryBuilder.setRequest(nextEditRequest);
360
457
  logContext.setRequestInput(nextEditRequest);
@@ -376,12 +473,6 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
376
473
  const activeDocSelection = doc.selection.get()[0];
377
474
  const projectedDocuments = historyContext.documents.map(doc => this._processDoc(doc));
378
475
  const xtabEditHistory = this._xtabHistoryTracker.getHistory();
379
- function convertLineEditToEdit(nextLineEdit, docId) {
380
- const doc = projectedDocuments.find(d => d.nextEditDoc.id === docId);
381
- const rootedLineEdit = new rootedLineEdit_1.RootedLineEdit(doc.documentAfterEdits, nextLineEdit);
382
- const suggestedEdit = rootedLineEdit.toEdit();
383
- return suggestedEdit;
384
- }
385
476
  const firstEdit = new async_1.DeferredPromise();
386
477
  const nLinesEditWindow = (shouldExpandEditWindow
387
478
  ? this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAutoExpandEditWindowLines, this._expService)
@@ -420,117 +511,132 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
420
511
  }
421
512
  });
422
513
  }) : undefined);
423
- const createPushEdit = () => {
424
- let ithEdit = -1;
425
- const statePerDoc = new cache_1.CachedFunction((id) => {
426
- const doc = projectedDocuments.find(d => d.nextEditDoc.id === id);
427
- if (!doc) {
428
- throw new errors_1.BugIndicatingError();
429
- }
430
- return {
431
- docContents: doc.documentAfterEdits,
432
- editsSoFar: stringEdit_1.StringEdit.empty,
433
- nextEdits: [],
434
- docId: id,
435
- };
436
- });
437
- const pushEdit = (result) => {
438
- const myLogger = logger.createSubLogger('pushEdit');
439
- ++ithEdit;
440
- myLogger.trace(`processing edit #${ithEdit} (starts at 0)`);
441
- if (result.isError()) { // either error or stream of edits ended
442
- // if there was a request made, and it ended without any edits, reset shouldExpandEditWindow
443
- if (ithEdit === 0 && result.err instanceof statelessNextEditProvider_1.NoNextEditReason.NoSuggestions) {
444
- myLogger.trace('resetting shouldExpandEditWindow to false due to NoSuggestions');
445
- this._shouldExpandEditWindow = false;
446
- }
447
- if (statePerDoc.get(curDocId).nextEdits.length) {
448
- myLogger.trace(`${statePerDoc.get(curDocId).nextEdits.length} edits returned`);
449
- }
450
- else {
451
- myLogger.trace(`no edit, reason: ${result.err.kind}`);
452
- if (result.err instanceof statelessNextEditProvider_1.NoNextEditReason.NoSuggestions) {
453
- const { documentBeforeEdits, window } = result.err;
454
- let reducedWindow = window;
455
- if (activeDocSelection && window) {
456
- const cursorOffset = activeDocSelection.endExclusive;
457
- const t = documentBeforeEdits.getTransformer();
458
- const cursorPosition = t.getPosition(cursorOffset);
459
- const lineOffset = t.getOffset(cursorPosition.with(undefined, 1));
460
- const lineEndOffset = t.getOffset(cursorPosition.with(undefined, t.getLineLength(cursorPosition.lineNumber) + 1));
461
- const reducedOffset = t.getOffset(t.getPosition(window.start).delta(1));
462
- const reducedEndPosition = t.getPosition(window.endExclusive).delta(-2);
463
- const reducedEndOffset = t.getOffset(reducedEndPosition.column > 1 ? reducedEndPosition.with(undefined, t.getLineLength(reducedEndPosition.lineNumber) + 1) : reducedEndPosition);
464
- reducedWindow = new offsetRange_1.OffsetRange(Math.min(reducedOffset, lineOffset), Math.max(reducedEndOffset, lineEndOffset));
465
- }
466
- this._nextEditCache.setNoNextEdit(curDocId, documentBeforeEdits, reducedWindow, req);
467
- }
468
- }
469
- {
470
- disp.dispose();
471
- removeFromPending();
472
- }
473
- if (!firstEdit.isSettled) {
474
- firstEdit.complete(result);
475
- }
476
- return;
514
+ const statePerDoc = new cache_1.CachedFunction((id) => {
515
+ const doc = projectedDocuments.find(d => d.nextEditDoc.id === id);
516
+ if (!doc) {
517
+ throw new errors_1.BugIndicatingError();
518
+ }
519
+ return {
520
+ docContents: doc.documentAfterEdits,
521
+ editsSoFar: stringEdit_1.StringEdit.empty,
522
+ nextEdits: [],
523
+ docId: id,
524
+ };
525
+ });
526
+ const editStream = this._statelessNextEditProvider.provideNextEdit(nextEditRequest, logger, logContext, nextEditRequest.cancellationTokenSource.token);
527
+ let ithEdit = -1;
528
+ const processEdit = (streamedEdit, telemetry) => {
529
+ ++ithEdit;
530
+ const myLogger = logger.createSubLogger('processEdit');
531
+ myLogger.trace(`processing edit #${ithEdit} (starts at 0)`);
532
+ // reset shouldExpandEditWindow to false when we get any edit
533
+ myLogger.trace('resetting shouldExpandEditWindow to false due to receiving an edit');
534
+ this._shouldExpandEditWindow = false;
535
+ const targetDocState = statePerDoc.get(streamedEdit.targetDocument ?? curDocId);
536
+ const singleLineEdit = streamedEdit.edit;
537
+ const lineEdit = new lineEdit_1.LineEdit([singleLineEdit]);
538
+ const edit = convertLineEditToEdit(lineEdit, projectedDocuments, targetDocState.docId);
539
+ const rebasedEdit = edit.tryRebase(targetDocState.editsSoFar);
540
+ if (rebasedEdit === undefined) {
541
+ myLogger.trace(`edit ${ithEdit} is undefined after rebasing`);
542
+ if (!firstEdit.isSettled) {
543
+ firstEdit.complete(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('Rebased edit is undefined'))));
477
544
  }
478
- // reset shouldExpandEditWindow to false when we get any edit
479
- myLogger.trace('resetting shouldExpandEditWindow to false due to receiving an edit');
545
+ return undefined;
546
+ }
547
+ targetDocState.editsSoFar = targetDocState.editsSoFar.compose(rebasedEdit);
548
+ let cachedEdit;
549
+ if (rebasedEdit.replacements.length === 0) {
550
+ myLogger.trace(`WARNING: ${ithEdit} has no edits`);
551
+ }
552
+ else if (rebasedEdit.replacements.length > 1) {
553
+ myLogger.trace(`WARNING: ${ithEdit} has ${rebasedEdit.replacements.length} edits, but expected only 1`);
554
+ }
555
+ else {
556
+ // populate the cache
557
+ const nextEditReplacement = rebasedEdit.replacements[0];
558
+ targetDocState.nextEdits.push(nextEditReplacement);
559
+ cachedEdit = this._nextEditCache.setKthNextEdit(targetDocState.docId, targetDocState.docContents, ithEdit === 0 ? streamedEdit.window : undefined, nextEditReplacement, ithEdit, ithEdit === 0 ? targetDocState.nextEdits : undefined, ithEdit === 0 ? nextEditRequest.intermediateUserEdit : undefined, req, { isFromCursorJump: streamedEdit.isFromCursorJump, originalEditWindow: streamedEdit.originalWindow });
560
+ myLogger.trace(`populated cache for ${ithEdit}`);
561
+ }
562
+ if (!firstEdit.isSettled) {
563
+ myLogger.trace('resolving firstEdit promise');
564
+ logContext.setResult(new rootedLineEdit_1.RootedLineEdit(targetDocState.docContents, lineEdit)); // this's correct without rebasing because this's the first edit
565
+ firstEdit.complete(cachedEdit ? result_1.Result.ok(cachedEdit) : result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(new Error('No cached edit'))));
566
+ }
567
+ targetDocState.docContents = rebasedEdit.applyOnText(targetDocState.docContents);
568
+ return cachedEdit;
569
+ };
570
+ const handleStreamEnd = (completionReason, lastTelemetry) => {
571
+ const myLogger = logger.createSubLogger('streamEnd');
572
+ // if there was a request made, and it ended without any edits, reset shouldExpandEditWindow
573
+ const hadNoEdits = ithEdit === -1;
574
+ if (hadNoEdits && completionReason instanceof statelessNextEditProvider_1.NoNextEditReason.NoSuggestions) {
575
+ myLogger.trace('resetting shouldExpandEditWindow to false due to NoSuggestions');
480
576
  this._shouldExpandEditWindow = false;
481
- const targetDocState = statePerDoc.get(result.val.targetDocument ?? curDocId);
482
- const singleLineEdit = result.val.edit;
483
- const lineEdit = new lineEdit_1.LineEdit([singleLineEdit]);
484
- const edit = convertLineEditToEdit(lineEdit, targetDocState.docId);
485
- const rebasedEdit = edit.tryRebase(targetDocState.editsSoFar);
486
- if (rebasedEdit === undefined) {
487
- myLogger.trace(`edit ${ithEdit} is undefined after rebasing`);
488
- if (!firstEdit.isSettled) {
489
- firstEdit.complete(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('Rebased edit is undefined'))));
490
- }
491
- return;
492
- }
493
- targetDocState.editsSoFar = targetDocState.editsSoFar.compose(rebasedEdit);
494
- let cachedEdit;
495
- if (rebasedEdit.replacements.length === 0) {
496
- myLogger.trace(`WARNING: ${ithEdit} has no edits`);
497
- }
498
- else if (rebasedEdit.replacements.length > 1) {
499
- myLogger.trace(`WARNING: ${ithEdit} has ${rebasedEdit.replacements.length} edits, but expected only 1`);
500
- }
501
- else {
502
- // populate the cache
503
- const nextEdit = rebasedEdit.replacements[0];
504
- targetDocState.nextEdits.push(nextEdit);
505
- cachedEdit = this._nextEditCache.setKthNextEdit(targetDocState.docId, targetDocState.docContents, ithEdit === 0 ? result.val.window : undefined, nextEdit, ithEdit, ithEdit === 0 ? targetDocState.nextEdits : undefined, ithEdit === 0 ? nextEditRequest.intermediateUserEdit : undefined, req, { isFromCursorJump: result.val.isFromCursorJump });
506
- myLogger.trace(`populated cache for ${ithEdit}`);
507
- }
508
- if (!firstEdit.isSettled) {
509
- myLogger.trace('resolving firstEdit promise');
510
- logContext.setResult(new rootedLineEdit_1.RootedLineEdit(targetDocState.docContents, lineEdit)); // this's correct without rebasing because this's the first edit
511
- firstEdit.complete(cachedEdit ? result_1.Result.ok(cachedEdit) : result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Unexpected(new Error('No cached edit'))));
577
+ }
578
+ if (statePerDoc.get(curDocId).nextEdits.length) {
579
+ myLogger.trace(`${statePerDoc.get(curDocId).nextEdits.length} edits returned`);
580
+ }
581
+ else {
582
+ myLogger.trace(`no edit, reason: ${completionReason.kind}`);
583
+ if (completionReason instanceof statelessNextEditProvider_1.NoNextEditReason.NoSuggestions) {
584
+ const { documentBeforeEdits, window } = completionReason;
585
+ const reducedWindow = window ? computeReducedWindow(window, activeDocSelection, documentBeforeEdits) : undefined;
586
+ this._nextEditCache.setNoNextEdit(curDocId, documentBeforeEdits, reducedWindow, req);
512
587
  }
513
- targetDocState.docContents = rebasedEdit.applyOnText(targetDocState.docContents);
514
- };
515
- return pushEdit;
588
+ }
589
+ if (!firstEdit.isSettled) {
590
+ firstEdit.complete(result_1.Result.error(completionReason));
591
+ }
592
+ const resultForTelemetry = statePerDoc.get(curDocId).nextEdits.length > 0
593
+ ? result_1.Result.ok(undefined)
594
+ : result_1.Result.error(completionReason);
595
+ const result = new statelessNextEditProvider_1.StatelessNextEditResult(resultForTelemetry, lastTelemetry);
596
+ nextEditRequest.setResult(result);
597
+ disp.dispose();
598
+ removeFromPending();
599
+ return result;
516
600
  };
517
- const pushEdit = createPushEdit();
518
601
  try {
519
- nextEditResult = await this._statelessNextEditProvider.provideNextEdit(nextEditRequest, pushEdit, logger, logContext, nextEditRequest.cancellationTokenSource.token);
520
- nextEditRequest.setResult(nextEditResult);
602
+ let res = await editStream.next();
603
+ if (res.done) {
604
+ // Stream ended immediately without any edits
605
+ const completionReason = res.value.v;
606
+ nextEditResult = handleStreamEnd(completionReason, res.value.telemetryBuilder);
607
+ }
608
+ else {
609
+ // Process first edit synchronously
610
+ const firstStreamedEdit = res.value.v;
611
+ const firstTelemetry = res.value.telemetryBuilder;
612
+ processEdit(firstStreamedEdit, firstTelemetry);
613
+ // Continue streaming remaining edits in the background (unawaited)
614
+ (async () => {
615
+ try {
616
+ res = await editStream.next();
617
+ while (!res.done) {
618
+ const streamedEdit = res.value.v;
619
+ processEdit(streamedEdit, res.value.telemetryBuilder);
620
+ res = await editStream.next();
621
+ }
622
+ // Stream completed
623
+ const completionReason = res.value.v;
624
+ handleStreamEnd(completionReason, res.value.telemetryBuilder);
625
+ }
626
+ catch (err) {
627
+ logger.trace(`Error while streaming further edits: ${errors.toString(err)}`);
628
+ const errorReason = new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors.fromUnknown(err));
629
+ handleStreamEnd(errorReason, firstTelemetry);
630
+ }
631
+ })();
632
+ // Return early with streaming result
633
+ nextEditResult = statelessNextEditProvider_1.StatelessNextEditResult.streaming(new statelessNextEditProvider_1.StatelessNextEditTelemetryBuilder(nextEditRequest.headerRequestId));
634
+ }
521
635
  }
522
636
  catch (err) {
523
637
  nextEditRequest.setResultError(err);
524
638
  throw err;
525
639
  }
526
- finally {
527
- if (!nextEditResult || nextEditResult.nextEdit.isError()) {
528
- // when streaming, we need to keep the response going unless UI cancels it
529
- // if we remove it from pending here, when UI cancels, we cannot cancel it because we think that the request has finished
530
- disp.dispose();
531
- removeFromPending();
532
- }
533
- }
534
640
  return { nextEditRequest, nextEditResult };
535
641
  }
536
642
  _hookupCancellation(nextEditRequest, cancellationToken, attachedDisposable) {
@@ -596,6 +702,235 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
596
702
  }
597
703
  handleShown(suggestion) {
598
704
  this._lastShownTime = Date.now();
705
+ this._lastShownSuggestionId = suggestion.requestId;
706
+ // Trigger speculative request for the post-edit document state
707
+ const speculativeRequestsEnablement = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsSpeculativeRequests, this._expService);
708
+ if (speculativeRequestsEnablement === xtabPromptOptions_1.SpeculativeRequestsEnablement.On) {
709
+ void this._triggerSpeculativeRequest(suggestion);
710
+ }
711
+ }
712
+ async _triggerSpeculativeRequest(suggestion) {
713
+ const logger = this._logger.createSubLogger('_triggerSpeculativeRequest');
714
+ const result = suggestion.result;
715
+ if (!result?.edit) {
716
+ logger.trace('no edit in suggestion result');
717
+ return;
718
+ }
719
+ const docId = result.targetDocumentId;
720
+ if (!docId) {
721
+ logger.trace('no target document ID in suggestion result');
722
+ return;
723
+ }
724
+ // Compute the post-edit document content
725
+ const postEditContent = result.edit.replace(result.documentBeforeEdits.value);
726
+ const postEditCursorOffset = result.edit.replaceRange.endExclusive + result.edit.getLengthDelta();
727
+ const selections = [new offsetRange_1.OffsetRange(postEditCursorOffset, postEditCursorOffset)];
728
+ const rootedEdit = new edit_1.RootedEdit(result.documentBeforeEdits, new stringEdit_1.StringEdit([result.edit]));
729
+ const postEditContentST = new abstractText_1.StringText(postEditContent);
730
+ let cachedEdit = this._nextEditCache.lookupNextEdit(docId, postEditContentST, selections);
731
+ let shiftedSelection;
732
+ if (cachedEdit) {
733
+ // first cachedEdit should be without edits because of noSuggestions caching
734
+ if (cachedEdit.edit) {
735
+ logger.trace('already have cached edit for post-edit state');
736
+ return;
737
+ }
738
+ else if (cachedEdit.editWindow) {
739
+ const trans = postEditContentST.getTransformer();
740
+ const endOfEditWindow = trans.getPosition(cachedEdit.editWindow.endExclusive - 1);
741
+ const shiftedCursorLineNumber = (endOfEditWindow.lineNumber + 1 < postEditContentST.lineRange.endLineNumberExclusive
742
+ ? endOfEditWindow.lineNumber + 1
743
+ : endOfEditWindow.lineNumber);
744
+ const shiftedSelectionCursorOffset = trans.getOffset(new position_1.Position(shiftedCursorLineNumber, 1));
745
+ shiftedSelection = new offsetRange_1.OffsetRange(shiftedSelectionCursorOffset, shiftedSelectionCursorOffset);
746
+ cachedEdit = this._nextEditCache.lookupNextEdit(docId, postEditContentST, [shiftedSelection]);
747
+ if (cachedEdit?.edit) {
748
+ logger.trace('already have cached edit for post-edit state (after shifting selection)');
749
+ return;
750
+ }
751
+ }
752
+ else {
753
+ logger.trace('already have cached no-suggestions entry for post-edit state');
754
+ return;
755
+ }
756
+ }
757
+ // Check if we already have a pending request for the post-edit state
758
+ if (this._pendingStatelessNextEditRequest?.documentBeforeEdits.value === postEditContent) {
759
+ logger.trace('already have pending request for post-edit state');
760
+ return;
761
+ }
762
+ // Check if we already have a speculative request for this post-edit state
763
+ if (this._speculativePendingRequest?.postEditContent === postEditContent) {
764
+ logger.trace('already have speculative request for post-edit state');
765
+ return;
766
+ }
767
+ // Get the document to trigger speculative fetch
768
+ // Note: targetDocumentId is defined when the suggestion targets a different document
769
+ // Otherwise, use the file path from the log context
770
+ const doc = this._workspace.getDocument(docId);
771
+ if (!doc) {
772
+ logger.trace('document not found for speculative request');
773
+ return;
774
+ }
775
+ // Cancel any previous speculative request
776
+ this._speculativePendingRequest?.request.cancellationTokenSource.cancel();
777
+ this._speculativePendingRequest = null;
778
+ const historyContext = this._historyContextProvider.getHistoryContext(docId);
779
+ if (!historyContext) {
780
+ logger.trace('no history context for speculative request');
781
+ return;
782
+ }
783
+ // Create a speculative request
784
+ // Use a dummy version since this is speculative and we don't have the actual post-edit version
785
+ const logContext = new inlineEditLogContext_1.InlineEditRequestLogContext(docId.uri, 0, undefined);
786
+ const req = new NextEditFetchRequest(`sp-${suggestion.source.opportunityId}`, logContext, undefined, `sp-${(0, uuid_1.generateUuid)()}`);
787
+ logger.trace(`triggering speculative request for post-edit state (opportunityId=${req.opportunityId}, headerRequestId=${req.headerRequestId})`);
788
+ logger.trace(`triggering speculative request for post-edit state (opportunityId=${req.opportunityId}, headerRequestId=${req.headerRequestId})`);
789
+ try {
790
+ const speculativeRequest = await this._createSpeculativeRequest(req, doc, shiftedSelection, historyContext, postEditContent, rootedEdit, result.edit, logger);
791
+ if (speculativeRequest) {
792
+ this._speculativePendingRequest = {
793
+ request: speculativeRequest,
794
+ postEditContent,
795
+ };
796
+ }
797
+ }
798
+ catch (e) {
799
+ logger.trace(`speculative request failed: ${errors.toString(e)}`);
800
+ }
801
+ }
802
+ /**
803
+ * Creates and starts a speculative request for the post-edit document state.
804
+ * The request will populate the cache so that when the user accepts the suggestion,
805
+ * the next NES request can reuse or find the result in cache.
806
+ */
807
+ async _createSpeculativeRequest(req, doc, shiftedSelection, historyContext, postEditContent, rootedEdit, appliedEdit, parentLogger) {
808
+ const logger = parentLogger.createSubLogger('_createSpeculativeRequest');
809
+ const curDocId = doc.id;
810
+ const recording = this._debugRecorder?.getRecentLog();
811
+ const logContext = req.log;
812
+ const activeDocAndIdx = historyContext.getDocumentAndIdx(curDocId);
813
+ if (!activeDocAndIdx) {
814
+ logger.trace('active doc not found in history context');
815
+ return undefined;
816
+ }
817
+ // Create the post-edit document content
818
+ const postEditText = new abstractText_1.StringText(postEditContent);
819
+ // Process documents, but for the active document, use the post-edit state
820
+ const projectedDocuments = historyContext.documents.map(docHist => {
821
+ if (docHist.docId !== curDocId) {
822
+ return this._processDoc(docHist);
823
+ }
824
+ else {
825
+ // For the active document, create a version representing post-edit state
826
+ // The "recent edit" from the model's perspective is the NES edit we just applied
827
+ const workspaceRoot = this._workspace.getWorkspaceRoot(curDocId);
828
+ const postEditEdit = new stringEdit_1.StringEdit([appliedEdit]);
829
+ const postEditLineEdit = rootedLineEdit_1.RootedLineEdit.fromEdit(new edit_1.RootedEdit(doc.value.get(), postEditEdit)).removeCommonSuffixPrefixLines().edit;
830
+ let selection = shiftedSelection;
831
+ if (selection === undefined) {
832
+ const appliedEditEndPos = postEditText.getTransformer().getPosition(appliedEdit.replaceRange.endExclusive + appliedEdit.getLengthDelta());
833
+ const pos = new position_1.Position(appliedEditEndPos.lineNumber, 1);
834
+ const offset = postEditText.getTransformer().getOffset(pos);
835
+ selection = new offsetRange_1.OffsetRange(offset, offset);
836
+ }
837
+ const nextEditDoc = new statelessNextEditProvider_1.StatelessNextEditDocument(curDocId, workspaceRoot, docHist.languageId, doc.value.get().getLines(), // lines before the NES edit
838
+ postEditLineEdit, // the NES edit as LineEdit
839
+ doc.value.get(), // document before NES edit
840
+ edit_1.Edits.single(postEditEdit), // the NES edit as Edits
841
+ selection);
842
+ return {
843
+ recentEdit: new edit_1.RootedEdit(doc.value.get(), postEditEdit),
844
+ nextEditDoc,
845
+ documentAfterEdits: postEditText,
846
+ };
847
+ }
848
+ });
849
+ const xtabEditHistory = this._xtabHistoryTracker.getHistory();
850
+ const suggestedEdit = { kind: 'edit', docId: curDocId, edit: rootedEdit };
851
+ xtabEditHistory.push(suggestedEdit);
852
+ const firstEdit = new async_1.DeferredPromise();
853
+ const nLinesEditWindow = this._configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsAutoExpandEditWindowLines, this._expService);
854
+ const nextEditRequest = new statelessNextEditProvider_1.StatelessNextEditRequest(req.headerRequestId, req.opportunityId, postEditText, // documentBeforeEdits is the post-edit state
855
+ projectedDocuments.map(d => d.nextEditDoc), activeDocAndIdx.idx, xtabEditHistory, firstEdit, nLinesEditWindow, logContext, undefined, // recordingBookmark
856
+ recording, undefined);
857
+ logger.trace('starting speculative provider call');
858
+ // Start the provider call - this runs in the background and populates the cache
859
+ const label = `NES | spec | ${(0, path_1.basename)(doc.id.toUri().fsPath)} (v${doc.version})`;
860
+ const capturingToken = new capturingToken_1.CapturingToken(label, undefined, true, true);
861
+ void this._requestLogger.captureInvocation(capturingToken, () => this._runSpeculativeProviderCall(nextEditRequest, projectedDocuments, curDocId, req, logger));
862
+ return nextEditRequest;
863
+ }
864
+ /**
865
+ * Runs the provider call for a speculative request and caches results.
866
+ */
867
+ async _runSpeculativeProviderCall(nextEditRequest, projectedDocuments, curDocId, req, parentLogger) {
868
+ const logger = parentLogger.createSubLogger('_runSpeculativeProviderCall');
869
+ const statePerDoc = new cache_1.CachedFunction((id) => {
870
+ const doc = projectedDocuments.find(d => d.nextEditDoc.id === id);
871
+ if (!doc) {
872
+ throw new errors_1.BugIndicatingError();
873
+ }
874
+ return {
875
+ docContents: doc.documentAfterEdits,
876
+ editsSoFar: stringEdit_1.StringEdit.empty,
877
+ nextEdits: [],
878
+ docId: id,
879
+ };
880
+ });
881
+ const logContext = req.log;
882
+ const editStream = this._statelessNextEditProvider.provideNextEdit(nextEditRequest, logger, logContext, nextEditRequest.cancellationTokenSource.token);
883
+ let ithEdit = -1;
884
+ try {
885
+ let res = await editStream.next();
886
+ if (res.done) {
887
+ nextEditRequest.firstEdit.complete(result_1.Result.error(res.value.v));
888
+ nextEditRequest.setResult(new statelessNextEditProvider_1.StatelessNextEditResult(result_1.Result.error(res.value.v), res.value.telemetryBuilder));
889
+ logger.trace('speculative request completed with no edits');
890
+ }
891
+ else {
892
+ (async () => {
893
+ while (!res.done) {
894
+ ++ithEdit;
895
+ const streamedEdit = res.value.v;
896
+ const targetDocState = statePerDoc.get(streamedEdit.targetDocument ?? curDocId);
897
+ const singleLineEdit = streamedEdit.edit;
898
+ const lineEdit = new lineEdit_1.LineEdit([singleLineEdit]);
899
+ const edit = convertLineEditToEdit(lineEdit, projectedDocuments, targetDocState.docId);
900
+ const rebasedEdit = edit.tryRebase(targetDocState.editsSoFar);
901
+ if (rebasedEdit === undefined) {
902
+ logger.trace(`speculative edit ${ithEdit} rebasing failed`);
903
+ res = await editStream.next();
904
+ continue;
905
+ }
906
+ targetDocState.editsSoFar = targetDocState.editsSoFar.compose(rebasedEdit);
907
+ if (rebasedEdit.replacements.length === 1) {
908
+ const nextEditReplacement = rebasedEdit.replacements[0];
909
+ targetDocState.nextEdits.push(nextEditReplacement);
910
+ // Populate the cache with the speculative result
911
+ const cachedEdit = this._nextEditCache.setKthNextEdit(targetDocState.docId, targetDocState.docContents, ithEdit === 0 ? streamedEdit.window : undefined, nextEditReplacement, ithEdit, ithEdit === 0 ? targetDocState.nextEdits : undefined, undefined, // no userEditSince for speculative
912
+ req, { isFromCursorJump: streamedEdit.isFromCursorJump, originalEditWindow: streamedEdit.originalWindow });
913
+ if (!nextEditRequest.firstEdit.isSettled && cachedEdit) {
914
+ nextEditRequest.firstEdit.complete(result_1.Result.ok(cachedEdit));
915
+ nextEditRequest.setResult(new statelessNextEditProvider_1.StatelessNextEditResult(result_1.Result.ok(undefined), res.value.telemetryBuilder));
916
+ }
917
+ logger.trace(`cached speculative edit ${ithEdit}`);
918
+ }
919
+ targetDocState.docContents = rebasedEdit.applyOnText(targetDocState.docContents);
920
+ res = await editStream.next();
921
+ }
922
+ })().finally(() => {
923
+ if (!nextEditRequest.firstEdit.isSettled) {
924
+ nextEditRequest.firstEdit.complete(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('Speculative request ended without edits'))));
925
+ nextEditRequest.setResult(new statelessNextEditProvider_1.StatelessNextEditResult(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('Speculative request ended without edits'))), res.value.telemetryBuilder));
926
+ }
927
+ });
928
+ }
929
+ logger.trace(`speculative request completed with ${ithEdit + 1} edits`);
930
+ }
931
+ catch (e) {
932
+ logger.trace(`speculative provider call error: ${errors.toString(e)}`);
933
+ }
599
934
  }
600
935
  handleAcceptance(docId, suggestion) {
601
936
  this.runSnippy(docId, suggestion);
@@ -621,7 +956,15 @@ let NextEditProvider = class NextEditProvider extends lifecycle_1.Disposable {
621
956
  this._lastRejectionTime = Date.now();
622
957
  this._statelessNextEditProvider.handleRejection?.();
623
958
  }
624
- handleIgnored(docId, suggestion, supersededBy) { }
959
+ handleIgnored(docId, suggestion, supersededBy) {
960
+ // Check if this was the last shown suggestion
961
+ const wasShown = this._lastShownSuggestionId === suggestion.requestId;
962
+ const wasSuperseded = supersededBy !== undefined;
963
+ if (wasShown && !wasSuperseded) {
964
+ // Was shown to the user
965
+ this._statelessNextEditProvider.handleIgnored?.();
966
+ }
967
+ }
625
968
  async runSnippy(docId, suggestion) {
626
969
  if (suggestion.result === undefined || suggestion.result.edit === undefined) {
627
970
  return;
@@ -638,7 +981,8 @@ exports.NextEditProvider = NextEditProvider = __decorate([
638
981
  __param(5, configurationService_1.IConfigurationService),
639
982
  __param(6, snippyService_1.ISnippyService),
640
983
  __param(7, logService_1.ILogService),
641
- __param(8, nullExperimentationService_1.IExperimentationService)
984
+ __param(8, nullExperimentationService_1.IExperimentationService),
985
+ __param(9, requestLogger_1.IRequestLogger)
642
986
  ], NextEditProvider);
643
987
  function assertDefined(value) {
644
988
  if (!value) {
@@ -647,11 +991,11 @@ function assertDefined(value) {
647
991
  return value;
648
992
  }
649
993
  class NextEditFetchRequest {
650
- constructor(opportunityId, log, providerRequestStartDateTime) {
994
+ constructor(opportunityId, log, providerRequestStartDateTime, headerRequestId = (0, uuid_1.generateUuid)()) {
651
995
  this.opportunityId = opportunityId;
652
996
  this.log = log;
653
997
  this.providerRequestStartDateTime = providerRequestStartDateTime;
654
- this.headerRequestId = (0, uuid_1.generateUuid)();
998
+ this.headerRequestId = headerRequestId;
655
999
  }
656
1000
  }
657
1001
  exports.NextEditFetchRequest = NextEditFetchRequest;