@vscode/chat-lib 0.0.4 → 0.0.5-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 (121) hide show
  1. package/dist/src/_internal/extension/byok/node/openAIEndpoint.d.ts +9 -0
  2. package/dist/src/_internal/extension/byok/node/openAIEndpoint.d.ts.map +1 -1
  3. package/dist/src/_internal/extension/byok/node/openAIEndpoint.js +136 -1
  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 +0 -1
  8. package/dist/src/_internal/extension/common/constants.js.map +1 -1
  9. package/dist/src/_internal/extension/inlineEdits/node/nesConfigs.d.ts +0 -4
  10. package/dist/src/_internal/extension/inlineEdits/node/nesConfigs.d.ts.map +1 -1
  11. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts +4 -2
  12. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts.map +1 -1
  13. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.js +15 -8
  14. package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.js.map +1 -1
  15. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts +0 -1
  16. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts.map +1 -1
  17. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js +9 -60
  18. package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js.map +1 -1
  19. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.d.ts.map +1 -1
  20. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js +7 -3
  21. package/dist/src/_internal/extension/inlineEdits/node/nextEditProviderTelemetry.js.map +1 -1
  22. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts.map +1 -1
  23. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js +46 -5
  24. package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js.map +1 -1
  25. package/dist/src/_internal/extension/xtab/common/promptCrafting.d.ts +25 -26
  26. package/dist/src/_internal/extension/xtab/common/promptCrafting.d.ts.map +1 -1
  27. package/dist/src/_internal/extension/xtab/common/promptCrafting.js +47 -37
  28. package/dist/src/_internal/extension/xtab/common/promptCrafting.js.map +1 -1
  29. package/dist/src/_internal/extension/xtab/common/xtabCurrentDocument.d.ts +16 -0
  30. package/dist/src/_internal/extension/xtab/common/xtabCurrentDocument.d.ts.map +1 -0
  31. package/dist/src/_internal/extension/xtab/common/xtabCurrentDocument.js +19 -0
  32. package/dist/src/_internal/extension/xtab/common/xtabCurrentDocument.js.map +1 -0
  33. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts +22 -4
  34. package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts.map +1 -1
  35. package/dist/src/_internal/extension/xtab/node/xtabProvider.js +361 -111
  36. package/dist/src/_internal/extension/xtab/node/xtabProvider.js.map +1 -1
  37. package/dist/src/_internal/platform/authentication/common/copilotToken.d.ts +1 -0
  38. package/dist/src/_internal/platform/authentication/common/copilotToken.d.ts.map +1 -1
  39. package/dist/src/_internal/platform/authentication/common/copilotToken.js +3 -0
  40. package/dist/src/_internal/platform/authentication/common/copilotToken.js.map +1 -1
  41. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.d.ts +13 -1
  42. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.d.ts.map +1 -1
  43. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.js +39 -9
  44. package/dist/src/_internal/platform/authentication/node/copilotTokenManager.js.map +1 -1
  45. package/dist/src/_internal/platform/chat/common/chatMLFetcher.d.ts +0 -1
  46. package/dist/src/_internal/platform/chat/common/chatMLFetcher.d.ts.map +1 -1
  47. package/dist/src/_internal/platform/chat/common/chatMLFetcher.js +1 -1
  48. package/dist/src/_internal/platform/chat/common/chatMLFetcher.js.map +1 -1
  49. package/dist/src/_internal/platform/chat/common/commonTypes.d.ts.map +1 -1
  50. package/dist/src/_internal/platform/chat/common/commonTypes.js +3 -1
  51. package/dist/src/_internal/platform/chat/common/commonTypes.js.map +1 -1
  52. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts +19 -11
  53. package/dist/src/_internal/platform/configuration/common/configurationService.d.ts.map +1 -1
  54. package/dist/src/_internal/platform/configuration/common/configurationService.js +21 -15
  55. package/dist/src/_internal/platform/configuration/common/configurationService.js.map +1 -1
  56. package/dist/src/_internal/platform/configuration/common/validator.d.ts +6 -0
  57. package/dist/src/_internal/platform/configuration/common/validator.d.ts.map +1 -1
  58. package/dist/src/_internal/platform/configuration/common/validator.js +41 -4
  59. package/dist/src/_internal/platform/configuration/common/validator.js.map +1 -1
  60. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts.map +1 -1
  61. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js +10 -5
  62. package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js.map +1 -1
  63. package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts +2 -1
  64. package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts.map +1 -1
  65. package/dist/src/_internal/platform/endpoint/common/endpointProvider.js.map +1 -1
  66. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts.map +1 -1
  67. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js +2 -1
  68. package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js.map +1 -1
  69. package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts +6 -0
  70. package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts.map +1 -1
  71. package/dist/src/_internal/platform/endpoint/node/responsesApi.js +161 -3
  72. package/dist/src/_internal/platform/endpoint/node/responsesApi.js.map +1 -1
  73. package/dist/src/_internal/platform/env/common/envService.d.ts +2 -0
  74. package/dist/src/_internal/platform/env/common/envService.d.ts.map +1 -1
  75. package/dist/src/_internal/platform/env/common/envService.js.map +1 -1
  76. package/dist/src/_internal/platform/env/common/nullEnvService.d.ts +1 -0
  77. package/dist/src/_internal/platform/env/common/nullEnvService.d.ts.map +1 -1
  78. package/dist/src/_internal/platform/env/common/nullEnvService.js +3 -0
  79. package/dist/src/_internal/platform/env/common/nullEnvService.js.map +1 -1
  80. package/dist/src/_internal/platform/github/common/githubAPI.d.ts +67 -0
  81. package/dist/src/_internal/platform/github/common/githubAPI.d.ts.map +1 -1
  82. package/dist/src/_internal/platform/github/common/githubAPI.js +120 -3
  83. package/dist/src/_internal/platform/github/common/githubAPI.js.map +1 -1
  84. package/dist/src/_internal/platform/github/common/githubService.d.ts +171 -1
  85. package/dist/src/_internal/platform/github/common/githubService.d.ts.map +1 -1
  86. package/dist/src/_internal/platform/github/common/githubService.js +34 -1
  87. package/dist/src/_internal/platform/github/common/githubService.js.map +1 -1
  88. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.d.ts +11 -0
  89. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.d.ts.map +1 -1
  90. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.js +8 -1
  91. package/dist/src/_internal/platform/inlineEdits/common/dataTypes/xtabPromptOptions.js.map +1 -1
  92. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js +2 -2
  93. package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js.map +1 -1
  94. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts +12 -2
  95. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.d.ts.map +1 -1
  96. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js +13 -0
  97. package/dist/src/_internal/platform/inlineEdits/common/statelessNextEditProvider.js.map +1 -1
  98. package/dist/src/_internal/platform/networking/common/fetch.d.ts +2 -1
  99. package/dist/src/_internal/platform/networking/common/fetch.d.ts.map +1 -1
  100. package/dist/src/_internal/platform/networking/common/fetch.js +1 -0
  101. package/dist/src/_internal/platform/networking/common/fetch.js.map +1 -1
  102. package/dist/src/_internal/platform/networking/common/fetcherService.d.ts +2 -0
  103. package/dist/src/_internal/platform/networking/common/fetcherService.d.ts.map +1 -1
  104. package/dist/src/_internal/platform/networking/common/fetcherService.js.map +1 -1
  105. package/dist/src/_internal/platform/networking/common/networking.d.ts +6 -2
  106. package/dist/src/_internal/platform/networking/common/networking.d.ts.map +1 -1
  107. package/dist/src/_internal/platform/networking/common/networking.js +4 -3
  108. package/dist/src/_internal/platform/networking/common/networking.js.map +1 -1
  109. package/dist/src/_internal/platform/networking/node/stream.d.ts.map +1 -1
  110. package/dist/src/_internal/platform/networking/node/stream.js +5 -3
  111. package/dist/src/_internal/platform/networking/node/stream.js.map +1 -1
  112. package/dist/src/_internal/platform/openai/node/fetch.d.ts +2 -1
  113. package/dist/src/_internal/platform/openai/node/fetch.d.ts.map +1 -1
  114. package/dist/src/_internal/platform/openai/node/fetch.js +20 -20
  115. package/dist/src/_internal/platform/openai/node/fetch.js.map +1 -1
  116. package/dist/src/_internal/util/common/cache.d.ts +1 -0
  117. package/dist/src/_internal/util/common/cache.d.ts.map +1 -1
  118. package/dist/src/_internal/util/common/cache.js +9 -0
  119. package/dist/src/_internal/util/common/cache.js.map +1 -1
  120. package/dist/src/package.json +225 -118
  121. package/package.json +3 -3
@@ -48,12 +48,16 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
48
48
  var XtabProvider_1;
49
49
  Object.defineProperty(exports, "__esModule", { value: true });
50
50
  exports.XtabProvider = void 0;
51
+ exports.findMergeConflictMarkersRange = findMergeConflictMarkersRange;
52
+ const copilot_api_1 = require("@vscode/copilot-api");
51
53
  const prompt_tsx_1 = require("@vscode/prompt-tsx");
54
+ const rawTypes_1 = require("@vscode/prompt-tsx/dist/base/output/rawTypes");
52
55
  const chatMLFetcher_1 = require("../../../platform/chat/common/chatMLFetcher");
53
56
  const commonTypes_1 = require("../../../platform/chat/common/commonTypes");
54
57
  const globalStringUtils_1 = require("../../../platform/chat/common/globalStringUtils");
55
58
  const configurationService_1 = require("../../../platform/configuration/common/configurationService");
56
59
  const diffService_1 = require("../../../platform/diff/common/diffService");
60
+ const chatEndpoint_1 = require("../../../platform/endpoint/node/chatEndpoint");
57
61
  const proxyXtabEndpoint_1 = require("../../../platform/endpoint/node/proxyXtabEndpoint");
58
62
  const ignoreService_1 = require("../../../platform/ignore/common/ignoreService");
59
63
  const xtabPromptOptions = __importStar(require("../../../platform/inlineEdits/common/dataTypes/xtabPromptOptions"));
@@ -66,12 +70,15 @@ const languageContextService_1 = require("../../../platform/languageServer/commo
66
70
  const logService_1 = require("../../../platform/log/common/logService");
67
71
  const simulationTestContext_1 = require("../../../platform/simulationTestContext/common/simulationTestContext");
68
72
  const nullExperimentationService_1 = require("../../../platform/telemetry/common/nullExperimentationService");
73
+ const telemetry_1 = require("../../../platform/telemetry/common/telemetry");
69
74
  const workspaceService_1 = require("../../../platform/workspace/common/workspaceService");
70
75
  const async_1 = require("../../../util/common/async");
71
76
  const errors = __importStar(require("../../../util/common/errors"));
72
77
  const result_1 = require("../../../util/common/result");
78
+ const tokenizer_1 = require("../../../util/common/tokenizer");
73
79
  const tracing_1 = require("../../../util/common/tracing");
74
80
  const async_2 = require("../../../util/vs/base/common/async");
81
+ const cancellation_1 = require("../../../util/vs/base/common/cancellation");
75
82
  const stopwatch_1 = require("../../../util/vs/base/common/stopwatch");
76
83
  const lineEdit_1 = require("../../../util/vs/editor/common/core/edits/lineEdit");
77
84
  const stringEdit_1 = require("../../../util/vs/editor/common/core/edits/stringEdit");
@@ -86,6 +93,7 @@ const ghNearbyNesProvider_1 = require("../../inlineEdits/common/ghNearbyNesProvi
86
93
  const nearbyCursorInlineEditProvider_1 = require("../../inlineEdits/common/nearbyCursorInlineEditProvider");
87
94
  const importFiltering_1 = require("../../inlineEdits/node/importFiltering");
88
95
  const promptCrafting_1 = require("../common/promptCrafting");
96
+ const xtabCurrentDocument_1 = require("../common/xtabCurrentDocument");
89
97
  const xtabEndpoint_1 = require("./xtabEndpoint");
90
98
  const xtabUtils_1 = require("./xtabUtils");
91
99
  var ResponseTags;
@@ -105,7 +113,8 @@ var ResponseTags;
105
113
  let XtabProvider = class XtabProvider {
106
114
  static { XtabProvider_1 = this; }
107
115
  static { this.ID = configurationService_1.XTabProviderId; }
108
- constructor(simulationCtx, instaService, workspaceService, diffService, configService, expService, logService, langCtxService, langDiagService, ignoreService) {
116
+ static { this.computeTokens = (s) => Math.floor(s.length / 4); }
117
+ constructor(simulationCtx, instaService, workspaceService, diffService, configService, expService, logService, langCtxService, langDiagService, ignoreService, telemetryService) {
109
118
  this.simulationCtx = simulationCtx;
110
119
  this.instaService = instaService;
111
120
  this.workspaceService = workspaceService;
@@ -116,6 +125,7 @@ let XtabProvider = class XtabProvider {
116
125
  this.langCtxService = langCtxService;
117
126
  this.langDiagService = langDiagService;
118
127
  this.ignoreService = ignoreService;
128
+ this.telemetryService = telemetryService;
119
129
  this.ID = XtabProvider_1.ID;
120
130
  this.dependsOnSelection = true;
121
131
  this.showNextEditPreference = "always" /* ShowNextEditPreference.Always */;
@@ -190,86 +200,48 @@ let XtabProvider = class XtabProvider {
190
200
  if (selection === null) {
191
201
  return result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('NoSelection')));
192
202
  }
193
- const endpoint = this.getEndpoint();
203
+ const promptOptions = this.determineModelConfiguration(activeDocument);
204
+ const endpoint = this.getEndpoint(promptOptions.modelName);
194
205
  logContext.setEndpointInfo(typeof endpoint.urlOrRequestMetadata === 'string' ? endpoint.urlOrRequestMetadata : JSON.stringify(endpoint.urlOrRequestMetadata.type), endpoint.model);
195
206
  telemetryBuilder.setModelName(endpoint.model);
196
- const computeTokens = (s) => Math.floor(s.length / 4);
197
207
  const cursorPosition = new position_1.Position(selection.endLineNumber, selection.endColumn);
198
- const cursorOffset = activeDocument.documentAfterEdits.getTransformer().getOffset(cursorPosition);
199
- const currentFileContent = activeDocument.documentAfterEdits;
200
- const currentFileContentLines = currentFileContent.getLines();
201
- const cursorLineIdx = cursorPosition.lineNumber - 1 /* to convert to 0-based */;
202
- const cursorLine = currentFileContentLines[cursorLineIdx];
208
+ const currentDocument = new xtabCurrentDocument_1.CurrentDocument(activeDocument.documentAfterEdits, cursorPosition);
209
+ const cursorLine = currentDocument.lines[currentDocument.cursorLineOffset];
203
210
  const isCursorAtEndOfLine = cursorPosition.column === cursorLine.trimEnd().length;
204
211
  if (isCursorAtEndOfLine) {
205
212
  delaySession.setExtraDebounce(this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsExtraDebounceEndOfLine, this.expService));
206
213
  }
207
214
  telemetryBuilder.setIsCursorAtLineEnd(isCursorAtEndOfLine);
208
- const areaAroundEditWindowLinesRange = this.computeAreaAroundEditWindowLinesRange(currentFileContentLines, cursorLineIdx);
209
- const editWindowLinesRange = this.computeEditWindowLinesRange(currentFileContentLines, cursorLineIdx, request, retryState);
210
- const cursorOriginalLinesOffset = Math.max(0, cursorLineIdx - editWindowLinesRange.start);
211
- const editWindowLastLineLength = activeDocument.documentAfterEdits.getTransformer().getLineLength(editWindowLinesRange.endExclusive);
212
- const editWindow = activeDocument.documentAfterEdits.getTransformer().getOffsetRange(new range_1.Range(editWindowLinesRange.start + 1, 1, editWindowLinesRange.endExclusive, editWindowLastLineLength + 1));
213
- const editWindowLines = currentFileContentLines.slice(editWindowLinesRange.start, editWindowLinesRange.endExclusive);
215
+ const areaAroundEditWindowLinesRange = this.computeAreaAroundEditWindowLinesRange(currentDocument);
216
+ const editWindowLinesRange = this.computeEditWindowLinesRange(currentDocument, request, retryState);
217
+ const cursorOriginalLinesOffset = Math.max(0, currentDocument.cursorLineOffset - editWindowLinesRange.start);
218
+ const editWindowLastLineLength = currentDocument.transformer.getLineLength(editWindowLinesRange.endExclusive);
219
+ const editWindow = currentDocument.transformer.getOffsetRange(new range_1.Range(editWindowLinesRange.start + 1, 1, editWindowLinesRange.endExclusive, editWindowLastLineLength + 1));
220
+ const editWindowLines = currentDocument.lines.slice(editWindowLinesRange.start, editWindowLinesRange.endExclusive);
214
221
  // Expected: editWindow.substring(activeDocument.documentAfterEdits.value) === editWindowLines.join('\n')
215
222
  const doesIncludeCursorTag = editWindowLines.some(line => line.includes(promptCrafting_1.PromptTags.CURSOR));
216
223
  const shouldRemoveCursorTagFromResponse = !doesIncludeCursorTag; // we'd like to remove the tag only if the original edit-window didn't include the tag
217
- const addCursorTagEdit = stringEdit_1.StringEdit.single(stringEdit_1.StringReplacement.insert(cursorOffset, promptCrafting_1.PromptTags.CURSOR));
218
- const contentWithCursor = addCursorTagEdit.applyOnText(currentFileContent);
219
- const contentWithCursorLines = contentWithCursor.getLines();
220
- const editWindowWithCursorLines = contentWithCursorLines.slice(editWindowLinesRange.start, editWindowLinesRange.endExclusive);
221
- const areaAroundCodeToEdit = [
222
- promptCrafting_1.PromptTags.AREA_AROUND.start,
223
- ...contentWithCursorLines.slice(areaAroundEditWindowLinesRange.start, editWindowLinesRange.start),
224
- promptCrafting_1.PromptTags.EDIT_WINDOW.start,
225
- ...editWindowWithCursorLines,
226
- promptCrafting_1.PromptTags.EDIT_WINDOW.end,
227
- ...contentWithCursorLines.slice(editWindowLinesRange.endExclusive, areaAroundEditWindowLinesRange.endExclusive),
228
- promptCrafting_1.PromptTags.AREA_AROUND.end
229
- ].join('\n');
230
- const promptOptions = this.determinePromptOptions(activeDocument);
231
- const areaAroundCodeToEditForCurrentFile = promptOptions.currentFile.includeTags
232
- ? areaAroundCodeToEdit
233
- : [
234
- ...contentWithCursorLines.slice(areaAroundEditWindowLinesRange.start, editWindowLinesRange.start),
235
- ...editWindowLines,
236
- ...contentWithCursorLines.slice(editWindowLinesRange.endExclusive, areaAroundEditWindowLinesRange.endExclusive),
237
- ].join('\n');
238
- const taggedCurrentFileContentResult = (0, promptCrafting_1.createTaggedCurrentFileContentUsingPagedClipping)(currentFileContentLines, areaAroundCodeToEditForCurrentFile, areaAroundEditWindowLinesRange, computeTokens, promptOptions.pagedClipping.pageSize, promptOptions.currentFile);
224
+ const taggedCurrentFileContentResult = this.constructTaggedFile(currentDocument, editWindowLinesRange, areaAroundEditWindowLinesRange, promptOptions, XtabProvider_1.computeTokens, { includeLineNumbers: false });
239
225
  if (taggedCurrentFileContentResult.isError()) {
240
226
  return result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('currentFile'));
241
227
  }
242
- const { taggedCurrentFileContent, nLines: nLinesCurrentFile } = taggedCurrentFileContentResult.val;
228
+ const { taggedCurrentFileR: { taggedCurrentFileContent, nLines: nLinesCurrentFile }, areaAroundCodeToEdit } = taggedCurrentFileContentResult.val;
243
229
  telemetryBuilder.setNLinesOfCurrentFileInPrompt(nLinesCurrentFile);
244
- const recordingEnabled = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsLogContextRecorderEnabled);
245
- let langCtx;
246
- if (promptOptions.languageContext.enabled || recordingEnabled) {
247
- const langCtxPromise = this.getLanguageContext(request, delaySession, activeDocument, cursorPosition, logContext, cancellationToken);
248
- if (promptOptions.languageContext.enabled) {
249
- langCtx = await langCtxPromise;
250
- }
251
- if (recordingEnabled) {
252
- logContext.setFileDiagnostics(this.langDiagService.getAllDiagnostics());
253
- langCtxPromise.then(langCtxs => {
254
- if (langCtxs) {
255
- logContext.setLanguageContext(langCtxs);
256
- }
257
- });
258
- }
230
+ const langCtx = await this.getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, logContext, cancellationToken);
231
+ if (cancellationToken.isCancellationRequested) {
232
+ return result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterLanguageContextAwait'));
259
233
  }
260
- const userPrompt = (0, promptCrafting_1.getUserPrompt)(activeDocument, request.xtabEditHistory, taggedCurrentFileContent, areaAroundCodeToEdit, langCtx, computeTokens, promptOptions);
234
+ const promptPieces = new promptCrafting_1.PromptPieces(currentDocument, editWindowLinesRange, areaAroundEditWindowLinesRange, activeDocument, request.xtabEditHistory, taggedCurrentFileContent, areaAroundCodeToEdit, langCtx, XtabProvider_1.computeTokens, promptOptions);
235
+ const userPrompt = (0, promptCrafting_1.getUserPrompt)(promptPieces);
261
236
  const prediction = this.getPredictedOutput(editWindowLines, promptOptions.promptingStrategy);
262
- const messages = [
263
- {
264
- role: prompt_tsx_1.Raw.ChatRole.System,
265
- content: (0, globalStringUtils_1.toTextParts)(this.pickSystemPrompt(promptOptions.promptingStrategy))
266
- },
267
- { role: prompt_tsx_1.Raw.ChatRole.User, content: (0, globalStringUtils_1.toTextParts)(userPrompt) }
268
- ];
237
+ const messages = constructMessages({
238
+ systemMsg: this.pickSystemPrompt(promptOptions.promptingStrategy),
239
+ userMsg: userPrompt,
240
+ });
269
241
  logContext.setPrompt(messages);
270
242
  telemetryBuilder.setPrompt(messages);
271
243
  const HARD_CHAR_LIMIT = 30000 * 4; // 30K tokens, assuming 4 chars per token -- we use approximation here because counting tokens exactly is time-consuming
272
- const promptCharCount = messages.reduce((total, msg) => total + msg.content.reduce((subtotal, part) => subtotal + part.text.length, 0), 0);
244
+ const promptCharCount = charCount(messages);
273
245
  if (promptCharCount > HARD_CHAR_LIMIT) {
274
246
  return result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('final'));
275
247
  }
@@ -279,13 +251,73 @@ let XtabProvider = class XtabProvider {
279
251
  }
280
252
  request.fetchIssued = true;
281
253
  const cursorLineOffset = cursorPosition.column;
282
- this.streamEdits(request, pushEdit, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, editWindowLinesRange, prediction, {
254
+ this.streamEdits(request, pushEdit, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, editWindowLinesRange, promptPieces, prediction, {
283
255
  shouldRemoveCursorTagFromResponse,
284
256
  promptingStrategy: promptOptions.promptingStrategy,
285
257
  retryState,
286
258
  }, delaySession, tracer, telemetryBuilder, logContext, cancellationToken);
287
259
  return result_1.Result.ok(undefined);
288
260
  }
261
+ constructTaggedFile(currentDocument, editWindowLinesRange, areaAroundEditWindowLinesRange, promptOptions, computeTokens, opts) {
262
+ const contentWithCursorAsLinesOriginal = (() => {
263
+ const addCursorTagEdit = stringEdit_1.StringEdit.single(stringEdit_1.StringReplacement.insert(currentDocument.cursorOffset, promptCrafting_1.PromptTags.CURSOR));
264
+ const contentWithCursor = addCursorTagEdit.applyOnText(currentDocument.content);
265
+ return contentWithCursor.getLines();
266
+ })();
267
+ const addLineNumbers = (lines) => lines.map((line, idx) => `${idx}| ${line}`);
268
+ const contentWithCursorAsLines = opts.includeLineNumbers
269
+ ? addLineNumbers(contentWithCursorAsLinesOriginal)
270
+ : contentWithCursorAsLinesOriginal;
271
+ const editWindowWithCursorAsLines = contentWithCursorAsLines.slice(editWindowLinesRange.start, editWindowLinesRange.endExclusive);
272
+ const areaAroundCodeToEdit = [
273
+ promptCrafting_1.PromptTags.AREA_AROUND.start,
274
+ ...contentWithCursorAsLines.slice(areaAroundEditWindowLinesRange.start, editWindowLinesRange.start),
275
+ promptCrafting_1.PromptTags.EDIT_WINDOW.start,
276
+ ...editWindowWithCursorAsLines,
277
+ promptCrafting_1.PromptTags.EDIT_WINDOW.end,
278
+ ...contentWithCursorAsLines.slice(editWindowLinesRange.endExclusive, areaAroundEditWindowLinesRange.endExclusive),
279
+ promptCrafting_1.PromptTags.AREA_AROUND.end
280
+ ].join('\n');
281
+ const currentFileContentLines = opts.includeLineNumbers
282
+ ? addLineNumbers(currentDocument.lines)
283
+ : currentDocument.lines;
284
+ let areaAroundCodeToEditForCurrentFile;
285
+ if (promptOptions.currentFile.includeTags) {
286
+ areaAroundCodeToEditForCurrentFile = areaAroundCodeToEdit;
287
+ }
288
+ else {
289
+ const editWindowLines = currentFileContentLines.slice(editWindowLinesRange.start, editWindowLinesRange.endExclusive);
290
+ areaAroundCodeToEditForCurrentFile = [
291
+ ...contentWithCursorAsLines.slice(areaAroundEditWindowLinesRange.start, editWindowLinesRange.start),
292
+ ...editWindowLines,
293
+ ...contentWithCursorAsLines.slice(editWindowLinesRange.endExclusive, areaAroundEditWindowLinesRange.endExclusive),
294
+ ].join('\n');
295
+ }
296
+ const taggedCurrentFileContentResult = (0, promptCrafting_1.createTaggedCurrentFileContentUsingPagedClipping)(currentFileContentLines, areaAroundCodeToEditForCurrentFile, areaAroundEditWindowLinesRange, computeTokens, promptOptions.pagedClipping.pageSize, promptOptions.currentFile);
297
+ return taggedCurrentFileContentResult.map(taggedCurrentFileR => ({
298
+ taggedCurrentFileR,
299
+ areaAroundCodeToEdit,
300
+ }));
301
+ }
302
+ getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, logContext, cancellationToken) {
303
+ const recordingEnabled = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsLogContextRecorderEnabled);
304
+ if (!promptOptions.languageContext.enabled && !recordingEnabled) {
305
+ return Promise.resolve(undefined);
306
+ }
307
+ const langCtxPromise = this.getLanguageContext(request, delaySession, activeDocument, cursorPosition, logContext, cancellationToken);
308
+ // if recording, add diagnostics for the file to the recording and hook up the language context promise to write to the recording
309
+ if (recordingEnabled) {
310
+ logContext.setFileDiagnostics(this.langDiagService.getAllDiagnostics());
311
+ langCtxPromise.then(langCtxs => {
312
+ if (langCtxs) {
313
+ logContext.setLanguageContext(langCtxs);
314
+ }
315
+ });
316
+ }
317
+ return promptOptions.languageContext.enabled
318
+ ? langCtxPromise
319
+ : Promise.resolve(undefined);
320
+ }
289
321
  async getLanguageContext(request, delaySession, activeDocument, cursorPosition, logContext, cancellationToken) {
290
322
  try {
291
323
  const textDoc = this.workspaceService.textDocuments.find(doc => doc.uri.toString() === activeDocument.id.uri);
@@ -348,8 +380,9 @@ let XtabProvider = class XtabProvider {
348
380
  }
349
381
  }
350
382
  async streamEdits(request, pushEdit, endpoint, messages, editWindow, editWindowLines, cursorOriginalLinesOffset, cursorLineOffset, // cursor offset within the line it's in; 1-based
351
- editWindowLineRange, prediction, opts, delaySession, parentTracer, telemetryBuilder, logContext, cancellationToken) {
383
+ editWindowLineRange, promptPieces, prediction, opts, delaySession, parentTracer, telemetryBuilder, logContext, cancellationToken) {
352
384
  const tracer = parentTracer.sub('streamEdits');
385
+ const useFetcher = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.NextEditSuggestionsFetcher, this.expService) || undefined;
353
386
  const fetchStreamSource = new chatMLFetcher_1.FetchStreamSource();
354
387
  const fetchRequestStopWatch = new stopwatch_1.StopWatch();
355
388
  let responseSoFar = '';
@@ -386,6 +419,7 @@ let XtabProvider = class XtabProvider {
386
419
  telemetryProperties: {
387
420
  requestId: request.id,
388
421
  },
422
+ useFetcher,
389
423
  }, cancellationToken);
390
424
  telemetryBuilder.setResponse(fetchResultPromise.then((response) => ({ response, ttft })));
391
425
  logContext.setFullResponse(fetchResultPromise.then((response) => response.type === commonTypes_1.ChatFetchResponseType.Success ? response.value : undefined));
@@ -453,7 +487,7 @@ let XtabProvider = class XtabProvider {
453
487
  }
454
488
  const trimmedLines = firstLine.value.trim();
455
489
  if (trimmedLines === ResponseTags.NO_CHANGE.start) {
456
- this.pushNoSuggestionsOrRetry(request, editWindow, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, opts.retryState);
490
+ await this.pushNoSuggestionsOrRetry(request, editWindow, promptPieces, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, opts.retryState);
457
491
  return;
458
492
  }
459
493
  if (trimmedLines === ResponseTags.INSERT.start) {
@@ -557,7 +591,7 @@ let XtabProvider = class XtabProvider {
557
591
  pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
558
592
  }
559
593
  else {
560
- this.pushNoSuggestionsOrRetry(request, editWindow, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, opts.retryState);
594
+ await this.pushNoSuggestionsOrRetry(request, editWindow, promptPieces, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, opts.retryState);
561
595
  }
562
596
  }
563
597
  catch (err) {
@@ -567,29 +601,58 @@ let XtabProvider = class XtabProvider {
567
601
  }
568
602
  })();
569
603
  }
570
- pushNoSuggestionsOrRetry(request, editWindow, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, retryState) {
604
+ async pushNoSuggestionsOrRetry(request, editWindow, promptPieces, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, retryState) {
571
605
  const allowRetryWithExpandedWindow = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderRetryWithNMoreLinesBelow, this.expService);
572
606
  // if allowed to retry and not retrying already, flip the retry state and try again
573
607
  if (allowRetryWithExpandedWindow && retryState === 0 /* RetryState.NotRetrying */ && request.expandedEditWindowNLines === undefined) {
574
- this.doGetNextEdit(request, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, 1 /* RetryState.RetryingWithExpandedWindow */);
608
+ this.doGetNextEdit(request, pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, 1 /* RetryState.Retrying */);
575
609
  return;
576
610
  }
611
+ const nextCursorLinePredictionEnabled = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsNextCursorPredictionEnabled, this.expService);
612
+ if (nextCursorLinePredictionEnabled && retryState === 0 /* RetryState.NotRetrying */) {
613
+ const nextCursorLineR = await this.predictNextCursorPosition(promptPieces);
614
+ if (nextCursorLineR.isError()) {
615
+ this.tracer.trace(`Predicted next cursor line error: ${nextCursorLineR.err.message}`);
616
+ telemetryBuilder.setNextCursorLineError(nextCursorLineR.err.message);
617
+ }
618
+ else {
619
+ const nextCursorLine = nextCursorLineR.val;
620
+ const lineDistanceFromCursorLine = nextCursorLine - promptPieces.currentDocument.cursorLineOffset;
621
+ telemetryBuilder.setNextCursorLineDistance(lineDistanceFromCursorLine);
622
+ this.tracer.trace(`Predicted next cursor line: ${nextCursorLine}`);
623
+ if (nextCursorLine >= promptPieces.currentDocument.lines.length) { // >= because the line index is zero-based
624
+ this.tracer.trace(`Predicted next cursor line error: exceedsDocumentLines`);
625
+ telemetryBuilder.setNextCursorLineError('exceedsDocumentLines');
626
+ }
627
+ else if (promptPieces.editWindowLinesRange.contains(nextCursorLine)) {
628
+ this.tracer.trace(`Predicted next cursor line error: withinEditWindow`);
629
+ telemetryBuilder.setNextCursorLineError('withinEditWindow');
630
+ }
631
+ else {
632
+ this.doGetNextEditWithSelection(request, new range_1.Range(nextCursorLine + 1, 1, nextCursorLine + 1, 1), pushEdit, delaySession, logContext, cancellationToken, telemetryBuilder, 1 /* RetryState.Retrying */);
633
+ return;
634
+ }
635
+ }
636
+ }
577
637
  pushEdit(result_1.Result.error(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow)));
578
638
  return;
579
639
  }
580
- computeAreaAroundEditWindowLinesRange(currentDocLines, cursorLine) {
640
+ computeAreaAroundEditWindowLinesRange(currentDocument) {
641
+ const cursorLine = currentDocument.cursorLineOffset;
581
642
  const areaAroundStart = Math.max(0, cursorLine - promptCrafting_1.N_LINES_AS_CONTEXT);
582
- const areaAroundEndExcl = Math.min(currentDocLines.length, cursorLine + promptCrafting_1.N_LINES_AS_CONTEXT + 1);
643
+ const areaAroundEndExcl = Math.min(currentDocument.lines.length, cursorLine + promptCrafting_1.N_LINES_AS_CONTEXT + 1);
583
644
  return new offsetRange_1.OffsetRange(areaAroundStart, areaAroundEndExcl);
584
645
  }
585
- computeEditWindowLinesRange(currentDocLines, cursorLine, request, retryState) {
646
+ computeEditWindowLinesRange(currentDocument, request, retryState) {
647
+ const currentDocLines = currentDocument.lines;
648
+ const cursorLineOffset = currentDocument.cursorLineOffset;
586
649
  let nLinesAbove;
587
650
  {
588
651
  const useVaryingLinesAbove = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderUseVaryingLinesAbove, this.expService);
589
652
  if (useVaryingLinesAbove) {
590
653
  nLinesAbove = 0; // default
591
654
  for (let i = 0; i < 8; ++i) {
592
- const lineIdx = cursorLine - i;
655
+ const lineIdx = cursorLineOffset - i;
593
656
  if (lineIdx < 0) {
594
657
  break;
595
658
  }
@@ -620,11 +683,28 @@ let XtabProvider = class XtabProvider {
620
683
  nLinesBelow = promptCrafting_1.N_LINES_BELOW; // default
621
684
  }
622
685
  }
623
- if (retryState === 1 /* RetryState.RetryingWithExpandedWindow */) {
686
+ if (retryState === 1 /* RetryState.Retrying */) {
624
687
  nLinesBelow += this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderRetryWithNMoreLinesBelow, this.expService) ?? 0;
625
688
  }
626
- const codeToEditStart = Math.max(0, cursorLine - nLinesAbove);
627
- const codeToEditEndExcl = Math.min(currentDocLines.length, cursorLine + nLinesBelow + 1);
689
+ let codeToEditStart = Math.max(0, cursorLineOffset - nLinesAbove);
690
+ let codeToEditEndExcl = Math.min(currentDocLines.length, cursorLineOffset + nLinesBelow + 1);
691
+ const maxMergeConflictLines = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabMaxMergeConflictLines, this.expService);
692
+ if (maxMergeConflictLines) {
693
+ const tentativeEditWindow = new offsetRange_1.OffsetRange(codeToEditStart, codeToEditEndExcl);
694
+ const mergeConflictRange = findMergeConflictMarkersRange(currentDocLines, tentativeEditWindow, maxMergeConflictLines);
695
+ if (mergeConflictRange) {
696
+ const onlyMergeConflictLines = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabOnlyMergeConflictLines, this.expService);
697
+ if (onlyMergeConflictLines) {
698
+ this.tracer.trace(`Expanding edit window to include ONLY merge conflict markers: ${mergeConflictRange.toString()}`);
699
+ codeToEditStart = mergeConflictRange.start;
700
+ codeToEditEndExcl = mergeConflictRange.endExclusive;
701
+ }
702
+ else {
703
+ this.tracer.trace(`Expanding edit window to include merge conflict markers: ${mergeConflictRange.toString()}; edit window range [${codeToEditStart}, ${codeToEditEndExcl})`);
704
+ codeToEditEndExcl = Math.max(codeToEditEndExcl, mergeConflictRange.endExclusive);
705
+ }
706
+ }
707
+ }
628
708
  return new offsetRange_1.OffsetRange(codeToEditStart, codeToEditEndExcl);
629
709
  }
630
710
  static mapChatFetcherErrorToNoNextEditReason(fetchError) {
@@ -650,40 +730,175 @@ let XtabProvider = class XtabProvider {
650
730
  return new statelessNextEditProvider_1.NoNextEditReason.FetchFailure(errors.fromUnknown(fetchError));
651
731
  }
652
732
  }
653
- determinePromptOptions(activeDocument) {
733
+ determineModelConfiguration(activeDocument) {
654
734
  if (this.forceUseDefaultModel) {
655
- return xtabPromptOptions.DEFAULT_OPTIONS;
656
- }
657
- else {
658
- const promptingStrategy = this.determinePromptingStrategy();
659
735
  return {
660
- promptingStrategy,
661
- currentFile: {
662
- maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabCurrentFileMaxTokens, this.expService),
663
- includeTags: promptingStrategy !== xtabPromptOptions.PromptingStrategy.UnifiedModel /* unified model doesn't use tags in current file */ && this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabIncludeTagsInCurrentFile, this.expService),
664
- prioritizeAboveCursor: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabPrioritizeAboveCursor, this.expService)
665
- },
666
- pagedClipping: {
667
- pageSize: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabPageSize, this.expService)
668
- },
669
- recentlyViewedDocuments: {
670
- nDocuments: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabNRecentlyViewedDocuments, this.expService),
671
- maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabRecentlyViewedDocumentsMaxTokens, this.expService),
672
- includeViewedFiles: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabIncludeViewedFiles, this.expService),
673
- },
674
- languageContext: this.determineLanguageContextOptions(activeDocument.languageId, {
675
- enabled: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabLanguageContextEnabled, this.expService),
676
- enabledLanguages: this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabLanguageContextEnabledLanguages),
677
- maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabLanguageContextMaxTokens, this.expService),
678
- }),
679
- diffHistory: {
680
- nEntries: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffNEntries, this.expService),
681
- maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffMaxTokens, this.expService),
682
- onlyForDocsInPrompt: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffOnlyForDocsInPrompt, this.expService),
683
- useRelativePaths: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffUseRelativePaths, this.expService),
684
- }
736
+ modelName: undefined,
737
+ ...xtabPromptOptions.DEFAULT_OPTIONS,
685
738
  };
686
739
  }
740
+ const promptingStrategy = this.determinePromptingStrategy();
741
+ const sourcedModelConfig = {
742
+ modelName: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderModelName, this.expService),
743
+ promptingStrategy,
744
+ currentFile: {
745
+ maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabCurrentFileMaxTokens, this.expService),
746
+ includeTags: promptingStrategy !== xtabPromptOptions.PromptingStrategy.UnifiedModel /* unified model doesn't use tags in current file */ && this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabIncludeTagsInCurrentFile, this.expService),
747
+ prioritizeAboveCursor: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabPrioritizeAboveCursor, this.expService)
748
+ },
749
+ pagedClipping: {
750
+ pageSize: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabPageSize, this.expService)
751
+ },
752
+ recentlyViewedDocuments: {
753
+ nDocuments: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabNRecentlyViewedDocuments, this.expService),
754
+ maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabRecentlyViewedDocumentsMaxTokens, this.expService),
755
+ includeViewedFiles: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabIncludeViewedFiles, this.expService),
756
+ },
757
+ languageContext: this.determineLanguageContextOptions(activeDocument.languageId, {
758
+ enabled: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabLanguageContextEnabled, this.expService),
759
+ enabledLanguages: this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabLanguageContextEnabledLanguages),
760
+ maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabLanguageContextMaxTokens, this.expService),
761
+ }),
762
+ diffHistory: {
763
+ nEntries: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffNEntries, this.expService),
764
+ maxTokens: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffMaxTokens, this.expService),
765
+ onlyForDocsInPrompt: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffOnlyForDocsInPrompt, this.expService),
766
+ useRelativePaths: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabDiffUseRelativePaths, this.expService),
767
+ },
768
+ includePostScript: true,
769
+ };
770
+ const localOverridingModelConfig = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderModelConfiguration);
771
+ if (localOverridingModelConfig) {
772
+ return XtabProvider_1.overrideModelConfig(sourcedModelConfig, localOverridingModelConfig);
773
+ }
774
+ const expBasedModelConfig = this.overrideByStringModelConfig(sourcedModelConfig, configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderModelConfigurationString);
775
+ if (expBasedModelConfig) {
776
+ return expBasedModelConfig;
777
+ }
778
+ const defaultModelConfig = this.overrideByStringModelConfig(sourcedModelConfig, configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderDefaultModelConfigurationString);
779
+ if (defaultModelConfig) {
780
+ return defaultModelConfig;
781
+ }
782
+ return sourcedModelConfig;
783
+ }
784
+ overrideByStringModelConfig(originalModelConfig, configKey) {
785
+ const configString = this.configService.getExperimentBasedConfig(configKey, this.expService);
786
+ if (configString === undefined) {
787
+ return undefined;
788
+ }
789
+ let parsedConfig;
790
+ try {
791
+ parsedConfig = JSON.parse(configString);
792
+ }
793
+ catch (e) {
794
+ /* __GDPR__
795
+ "incorrectNesModelConfig" : {
796
+ "owner": "ulugbekna",
797
+ "comment": "Capture if model configuration string is invalid JSON.",
798
+ "configName": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Name of the configuration that failed to parse." },
799
+ "errorMessage": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Error message from JSON.parse." },
800
+ "configValue": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The invalid JSON string." }
801
+ }
802
+ */
803
+ this.telemetryService.sendMSFTTelemetryEvent('incorrectNesModelConfig', { configName: configKey.id, errorMessage: errors.toString(errors.fromUnknown(e)), configValue: configString });
804
+ }
805
+ if (parsedConfig) {
806
+ return XtabProvider_1.overrideModelConfig(originalModelConfig, parsedConfig);
807
+ }
808
+ return undefined;
809
+ }
810
+ static overrideModelConfig(modelConfig, overridingConfig) {
811
+ return {
812
+ ...modelConfig,
813
+ modelName: overridingConfig.modelName,
814
+ promptingStrategy: overridingConfig.promptingStrategy,
815
+ currentFile: {
816
+ ...modelConfig.currentFile,
817
+ includeTags: overridingConfig.includeTagsInCurrentFile,
818
+ },
819
+ };
820
+ }
821
+ async predictNextCursorPosition(promptPieces) {
822
+ const tracer = this.tracer.sub('predictNextCursorPosition');
823
+ const systemMessage = 'Your task is to predict the next line number in the current file where the developer is most likely to make their next edit, using the provided context.';
824
+ const currentFileContentR = this.constructTaggedFile(promptPieces.currentDocument, promptPieces.editWindowLinesRange, promptPieces.areaAroundEditWindowLinesRange, {
825
+ ...promptPieces.opts,
826
+ currentFile: {
827
+ ...promptPieces.opts.currentFile,
828
+ includeTags: false,
829
+ }
830
+ }, XtabProvider_1.computeTokens, { includeLineNumbers: true });
831
+ if (currentFileContentR.isError()) {
832
+ tracer.trace(`Failed to construct tagged file: ${currentFileContentR.err}`);
833
+ return result_1.Result.fromString(currentFileContentR.err);
834
+ }
835
+ const { taggedCurrentFileR: { taggedCurrentFileContent }, areaAroundCodeToEdit } = currentFileContentR.val;
836
+ const newPromptPieces = new promptCrafting_1.PromptPieces(promptPieces.currentDocument, promptPieces.editWindowLinesRange, promptPieces.areaAroundEditWindowLinesRange, promptPieces.activeDoc, promptPieces.xtabHistory, taggedCurrentFileContent, areaAroundCodeToEdit, promptPieces.langCtx, XtabProvider_1.computeTokens, {
837
+ ...promptPieces.opts,
838
+ includePostScript: false,
839
+ });
840
+ const userMessage = (0, promptCrafting_1.getUserPrompt)(newPromptPieces);
841
+ const messages = constructMessages({
842
+ systemMsg: systemMessage,
843
+ userMsg: userMessage
844
+ });
845
+ const modelName = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsNextCursorPredictionModelName, this.expService);
846
+ if (modelName === undefined) {
847
+ tracer.trace('Model name for cursor prediction is not defined; skipping prediction');
848
+ return result_1.Result.fromString('modelNameNotDefined');
849
+ }
850
+ const url = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsNextCursorPredictionUrl);
851
+ const secretKey = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsNextCursorPredictionApiKey);
852
+ const endpoint = this.instaService.createInstance(chatEndpoint_1.ChatEndpoint, {
853
+ id: modelName,
854
+ name: 'nes.nextCursorPosition',
855
+ urlOrRequestMetadata: url ? url : { type: copilot_api_1.RequestType.ProxyChatCompletions },
856
+ model_picker_enabled: false,
857
+ is_chat_default: false,
858
+ is_chat_fallback: false,
859
+ version: '',
860
+ capabilities: {
861
+ type: 'chat',
862
+ family: '',
863
+ tokenizer: tokenizer_1.TokenizerType.CL100K,
864
+ limits: undefined,
865
+ supports: {
866
+ parallel_tool_calls: false,
867
+ tool_calls: false,
868
+ streaming: true,
869
+ vision: false,
870
+ prediction: false,
871
+ thinking: false
872
+ }
873
+ },
874
+ });
875
+ const response = await endpoint.makeChatRequest2({
876
+ messages,
877
+ debugName: 'nes.nextCursorPosition',
878
+ finishedCb: undefined,
879
+ location: commonTypes_1.ChatLocation.Other,
880
+ requestOptions: secretKey ? {
881
+ secretKey,
882
+ } : undefined,
883
+ }, cancellation_1.CancellationToken.None);
884
+ if (response.type !== commonTypes_1.ChatFetchResponseType.Success) {
885
+ return result_1.Result.fromString(`fetchError:${response.type}`);
886
+ }
887
+ try {
888
+ const trimmed = response.value.trim();
889
+ const lineNumber = parseInt(trimmed, 10);
890
+ if (isNaN(lineNumber)) {
891
+ return result_1.Result.fromString(`gotNaN`);
892
+ }
893
+ if (lineNumber < 0) {
894
+ return result_1.Result.fromString(`negativeLineNumber`);
895
+ }
896
+ return result_1.Result.ok(lineNumber);
897
+ }
898
+ catch (err) {
899
+ tracer.trace(`Failed to parse predicted line number from response '${response.value}': ${err}`);
900
+ return result_1.Result.fromString(`failedToParseLine:"${response.value}". Error ${errors.fromUnknown(err).message}`);
901
+ }
687
902
  }
688
903
  determinePromptingStrategy() {
689
904
  const isXtabUnifiedModel = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabUseUnifiedModel, this.expService);
@@ -732,18 +947,14 @@ let XtabProvider = class XtabProvider {
732
947
  }
733
948
  return { enabled, maxTokens };
734
949
  }
735
- getEndpoint() {
950
+ getEndpoint(configuredModelName) {
736
951
  const url = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderUrl);
737
952
  const apiKey = this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderApiKey);
738
953
  const hasOverriddenUrlAndApiKey = url !== undefined && apiKey !== undefined;
739
- const configuredModelName = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderModelName, this.expService);
740
954
  if (hasOverriddenUrlAndApiKey) {
741
955
  return this.instaService.createInstance(xtabEndpoint_1.XtabEndpoint, url, apiKey, configuredModelName);
742
956
  }
743
- const modelName = this.forceUseDefaultModel
744
- ? undefined
745
- : this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderModelName, this.expService);
746
- return (0, proxyXtabEndpoint_1.createProxyXtabEndpoint)(this.instaService, modelName);
957
+ return (0, proxyXtabEndpoint_1.createProxyXtabEndpoint)(this.instaService, configuredModelName);
747
958
  }
748
959
  getPredictedOutput(editWindowLines, promptingStrategy) {
749
960
  return this.configService.getConfig(configurationService_1.ConfigKey.Internal.InlineEditsXtabProviderUsePrediction)
@@ -802,6 +1013,45 @@ exports.XtabProvider = XtabProvider = XtabProvider_1 = __decorate([
802
1013
  __param(6, logService_1.ILogService),
803
1014
  __param(7, languageContextProviderService_1.ILanguageContextProviderService),
804
1015
  __param(8, languageDiagnosticsService_1.ILanguageDiagnosticsService),
805
- __param(9, ignoreService_1.IIgnoreService)
1016
+ __param(9, ignoreService_1.IIgnoreService),
1017
+ __param(10, telemetry_1.ITelemetryService)
806
1018
  ], XtabProvider);
1019
+ /**
1020
+ * Finds the range of lines containing merge conflict markers within a specified edit window.
1021
+ *
1022
+ * @param lines - Array of strings representing the lines of text to search through
1023
+ * @param editWindowRange - The range within which to search for merge conflict markers
1024
+ * @param maxMergeConflictLines - Maximum number of lines to search for conflict markers
1025
+ * @returns An OffsetRange object representing the start and end of the conflict markers, or undefined if not found
1026
+ */
1027
+ function findMergeConflictMarkersRange(lines, editWindowRange, maxMergeConflictLines) {
1028
+ for (let i = editWindowRange.start; i < Math.min(lines.length, editWindowRange.endExclusive); ++i) {
1029
+ if (!lines[i].startsWith('<<<<<<<')) {
1030
+ continue;
1031
+ }
1032
+ // found start of merge conflict markers -- now find the end
1033
+ for (let j = i + 1; j < lines.length && (j - i) < maxMergeConflictLines; ++j) {
1034
+ if (lines[j].startsWith('>>>>>>>')) {
1035
+ return new offsetRange_1.OffsetRange(i, j + 1 /* because endExclusive */);
1036
+ }
1037
+ }
1038
+ }
1039
+ return undefined;
1040
+ }
1041
+ function constructMessages({ systemMsg, userMsg }) {
1042
+ return [
1043
+ {
1044
+ role: prompt_tsx_1.Raw.ChatRole.System,
1045
+ content: (0, globalStringUtils_1.toTextParts)(systemMsg)
1046
+ },
1047
+ {
1048
+ role: prompt_tsx_1.Raw.ChatRole.User,
1049
+ content: (0, globalStringUtils_1.toTextParts)(userMsg)
1050
+ }
1051
+ ];
1052
+ }
1053
+ function charCount(messages) {
1054
+ const promptCharCount = messages.reduce((total, msg) => total + msg.content.reduce((subtotal, part) => subtotal + (part.type === rawTypes_1.ChatCompletionContentPartKind.Text ? part.text.length : 0), 0), 0);
1055
+ return promptCharCount;
1056
+ }
807
1057
  //# sourceMappingURL=xtabProvider.js.map