@vscode/chat-lib 0.4.0 → 0.4.1-0

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