@vscode/chat-lib 0.43.2026040705 → 0.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.d.ts +1 -5
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.d.ts.map +1 -1
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.js +3 -11
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/ghostText/completionsFromNetwork.js.map +1 -1
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/networking.d.ts +0 -30
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/networking.d.ts.map +1 -1
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/networking.js +4 -82
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/networking.js.map +1 -1
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.d.ts +2 -10
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.d.ts.map +1 -1
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.js +6 -160
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/fetch.js.map +1 -1
- package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts +11 -0
- package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.d.ts.map +1 -1
- package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.js +21 -3
- package/dist/src/_internal/extension/inlineEdits/node/nextEditCache.js.map +1 -1
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts +2 -2
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.d.ts.map +1 -1
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js +34 -12
- package/dist/src/_internal/extension/inlineEdits/node/nextEditProvider.js.map +1 -1
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts +1 -1
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.d.ts.map +1 -1
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js +22 -15
- package/dist/src/_internal/extension/prompt/node/chatMLFetcher.js.map +1 -1
- package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.js +2 -2
- package/dist/src/_internal/extension/prompt/node/chatMLFetcherTelemetry.js.map +1 -1
- package/dist/src/_internal/extension/xtab/node/cursorLineDivergence.d.ts +41 -0
- package/dist/src/_internal/extension/xtab/node/cursorLineDivergence.d.ts.map +1 -0
- package/dist/src/_internal/extension/xtab/node/cursorLineDivergence.js +181 -0
- package/dist/src/_internal/extension/xtab/node/cursorLineDivergence.js.map +1 -0
- package/dist/src/_internal/extension/xtab/node/editIntent.d.ts +31 -0
- package/dist/src/_internal/extension/xtab/node/editIntent.d.ts.map +1 -0
- package/dist/src/_internal/extension/xtab/node/editIntent.js +193 -0
- package/dist/src/_internal/extension/xtab/node/editIntent.js.map +1 -0
- package/dist/src/_internal/extension/xtab/node/responseFormatHandlers.d.ts +52 -0
- package/dist/src/_internal/extension/xtab/node/responseFormatHandlers.d.ts.map +1 -0
- package/dist/src/_internal/extension/xtab/node/responseFormatHandlers.js +159 -0
- package/dist/src/_internal/extension/xtab/node/responseFormatHandlers.js.map +1 -0
- package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts +10 -37
- package/dist/src/_internal/extension/xtab/node/xtabProvider.d.ts.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabProvider.js +277 -349
- package/dist/src/_internal/extension/xtab/node/xtabProvider.js.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabUtils.d.ts +10 -0
- package/dist/src/_internal/extension/xtab/node/xtabUtils.d.ts.map +1 -1
- package/dist/src/_internal/extension/xtab/node/xtabUtils.js +24 -0
- package/dist/src/_internal/extension/xtab/node/xtabUtils.js.map +1 -1
- package/dist/src/_internal/platform/authentication/common/copilotToken.d.ts +1 -0
- package/dist/src/_internal/platform/authentication/common/copilotToken.d.ts.map +1 -1
- package/dist/src/_internal/platform/authentication/common/copilotToken.js +3 -0
- package/dist/src/_internal/platform/authentication/common/copilotToken.js.map +1 -1
- package/dist/src/_internal/platform/chat/common/commonTypes.d.ts.map +1 -1
- package/dist/src/_internal/platform/chat/common/commonTypes.js +34 -4
- package/dist/src/_internal/platform/chat/common/commonTypes.js.map +1 -1
- package/dist/src/_internal/platform/configuration/common/configurationService.d.ts +17 -4
- package/dist/src/_internal/platform/configuration/common/configurationService.d.ts.map +1 -1
- package/dist/src/_internal/platform/configuration/common/configurationService.js +22 -9
- package/dist/src/_internal/platform/configuration/common/configurationService.js.map +1 -1
- package/dist/src/_internal/platform/configuration/common/defaultsOnlyConfigurationService.d.ts +1 -1
- package/dist/src/_internal/platform/configuration/common/defaultsOnlyConfigurationService.d.ts.map +1 -1
- package/dist/src/_internal/platform/configuration/common/defaultsOnlyConfigurationService.js +1 -1
- package/dist/src/_internal/platform/configuration/common/defaultsOnlyConfigurationService.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts +20 -0
- package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js +45 -1
- package/dist/src/_internal/platform/endpoint/common/chatModelCapabilities.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts +2 -0
- package/dist/src/_internal/platform/endpoint/common/endpointProvider.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/common/endpointProvider.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/common/statefulMarkerContainer.d.ts +5 -0
- package/dist/src/_internal/platform/endpoint/common/statefulMarkerContainer.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/common/statefulMarkerContainer.js +13 -0
- package/dist/src/_internal/platform/endpoint/common/statefulMarkerContainer.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts +3 -1
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js +14 -14
- package/dist/src/_internal/platform/endpoint/node/chatEndpoint.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/messagesApi.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/messagesApi.js +28 -12
- package/dist/src/_internal/platform/endpoint/node/messagesApi.js.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts +12 -2
- package/dist/src/_internal/platform/endpoint/node/responsesApi.d.ts.map +1 -1
- package/dist/src/_internal/platform/endpoint/node/responsesApi.js +201 -23
- package/dist/src/_internal/platform/endpoint/node/responsesApi.js.map +1 -1
- package/dist/src/_internal/platform/git/common/gitService.d.ts +7 -3
- package/dist/src/_internal/platform/git/common/gitService.d.ts.map +1 -1
- package/dist/src/_internal/platform/git/common/gitService.js.map +1 -1
- package/dist/src/_internal/platform/github/common/githubAPI.d.ts +1 -0
- package/dist/src/_internal/platform/github/common/githubAPI.d.ts.map +1 -1
- package/dist/src/_internal/platform/github/common/githubAPI.js +2 -0
- package/dist/src/_internal/platform/github/common/githubAPI.js.map +1 -1
- package/dist/src/_internal/platform/github/common/githubService.d.ts +3 -2
- package/dist/src/_internal/platform/github/common/githubService.d.ts.map +1 -1
- package/dist/src/_internal/platform/github/common/githubService.js.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts +12 -3
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.d.ts.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js +72 -46
- package/dist/src/_internal/platform/inlineEdits/common/inlineEditLogContext.js.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/utils/utils.d.ts +3 -0
- package/dist/src/_internal/platform/inlineEdits/common/utils/utils.d.ts.map +1 -1
- package/dist/src/_internal/platform/inlineEdits/common/utils/utils.js +12 -0
- package/dist/src/_internal/platform/inlineEdits/common/utils/utils.js.map +1 -1
- package/dist/src/_internal/platform/log/common/logService.d.ts +5 -0
- package/dist/src/_internal/platform/log/common/logService.d.ts.map +1 -1
- package/dist/src/_internal/platform/log/common/logService.js +22 -0
- package/dist/src/_internal/platform/log/common/logService.js.map +1 -1
- package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.d.ts +1 -1
- package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.d.ts.map +1 -1
- package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.js +1 -1
- package/dist/src/_internal/platform/nesFetch/node/completionsFetchServiceImpl.js.map +1 -1
- package/dist/src/_internal/platform/networking/common/anthropic.d.ts +0 -16
- package/dist/src/_internal/platform/networking/common/anthropic.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/common/anthropic.js +10 -42
- package/dist/src/_internal/platform/networking/common/anthropic.js.map +1 -1
- package/dist/src/_internal/platform/networking/common/fetcherService.d.ts +1 -0
- package/dist/src/_internal/platform/networking/common/fetcherService.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/common/fetcherService.js.map +1 -1
- package/dist/src/_internal/platform/networking/common/networking.d.ts +22 -4
- package/dist/src/_internal/platform/networking/common/networking.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/common/networking.js.map +1 -1
- package/dist/src/_internal/platform/networking/node/chatStream.d.ts +10 -0
- package/dist/src/_internal/platform/networking/node/chatStream.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/node/chatStream.js +28 -0
- package/dist/src/_internal/platform/networking/node/chatStream.js.map +1 -1
- package/dist/src/_internal/platform/networking/node/chatWebSocketManager.d.ts +23 -5
- package/dist/src/_internal/platform/networking/node/chatWebSocketManager.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/node/chatWebSocketManager.js +67 -20
- package/dist/src/_internal/platform/networking/node/chatWebSocketManager.js.map +1 -1
- package/dist/src/_internal/platform/networking/node/chatWebSocketTelemetry.d.ts +15 -1
- package/dist/src/_internal/platform/networking/node/chatWebSocketTelemetry.d.ts.map +1 -1
- package/dist/src/_internal/platform/networking/node/chatWebSocketTelemetry.js +51 -7
- package/dist/src/_internal/platform/networking/node/chatWebSocketTelemetry.js.map +1 -1
- package/dist/src/_internal/platform/requestLogger/common/requestLogger.d.ts +171 -0
- package/dist/src/_internal/platform/requestLogger/common/requestLogger.d.ts.map +1 -0
- package/dist/src/_internal/platform/requestLogger/common/requestLogger.js +145 -0
- package/dist/src/_internal/platform/requestLogger/common/requestLogger.js.map +1 -0
- package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.d.ts +2 -1
- package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.d.ts.map +1 -1
- package/dist/src/_internal/platform/requestLogger/node/nullRequestLogger.js.map +1 -1
- package/dist/src/_internal/platform/requestLogger/node/requestLogger.d.ts +4 -166
- package/dist/src/_internal/platform/requestLogger/node/requestLogger.d.ts.map +1 -1
- package/dist/src/_internal/platform/requestLogger/node/requestLogger.js +3 -139
- package/dist/src/_internal/platform/requestLogger/node/requestLogger.js.map +1 -1
- package/dist/src/main.d.ts +2 -0
- package/dist/src/main.d.ts.map +1 -1
- package/dist/src/main.js +48 -6
- package/dist/src/main.js.map +1 -1
- package/dist/src/package.json +106 -96
- package/package.json +71 -71
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/stream.d.ts +0 -182
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/stream.d.ts.map +0 -1
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/stream.js +0 -558
- package/dist/src/_internal/extension/completions-core/vscode-node/lib/src/openai/stream.js.map +0 -1
|
@@ -47,7 +47,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
47
47
|
};
|
|
48
48
|
var XtabProvider_1;
|
|
49
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
-
exports.
|
|
50
|
+
exports.XtabProvider = void 0;
|
|
51
51
|
exports.filterOutEditsWithSubstrings = filterOutEditsWithSubstrings;
|
|
52
52
|
exports.computeAreaAroundEditWindowLinesRange = computeAreaAroundEditWindowLinesRange;
|
|
53
53
|
exports.mapChatFetcherErrorToNoNextEditReason = mapChatFetcherErrorToNoNextEditReason;
|
|
@@ -55,8 +55,6 @@ exports.overrideModelConfig = overrideModelConfig;
|
|
|
55
55
|
exports.pickSystemPrompt = pickSystemPrompt;
|
|
56
56
|
exports.determineLanguageContextOptions = determineLanguageContextOptions;
|
|
57
57
|
exports.getPredictionContents = getPredictionContents;
|
|
58
|
-
exports.parseEditIntentFromStream = parseEditIntentFromStream;
|
|
59
|
-
exports.findMergeConflictMarkersRange = findMergeConflictMarkersRange;
|
|
60
58
|
const chatMLFetcher_1 = require("../../../platform/chat/common/chatMLFetcher");
|
|
61
59
|
const commonTypes_1 = require("../../../platform/chat/common/commonTypes");
|
|
62
60
|
const configurationService_1 = require("../../../platform/configuration/common/configurationService");
|
|
@@ -85,6 +83,7 @@ const errors_1 = require("../../../util/common/errors");
|
|
|
85
83
|
const result_1 = require("../../../util/common/result");
|
|
86
84
|
const assert_1 = require("../../../util/vs/base/common/assert");
|
|
87
85
|
const async_2 = require("../../../util/vs/base/common/async");
|
|
86
|
+
const cancellation_1 = require("../../../util/vs/base/common/cancellation");
|
|
88
87
|
const path_1 = require("../../../util/vs/base/common/path");
|
|
89
88
|
const stopwatch_1 = require("../../../util/vs/base/common/stopwatch");
|
|
90
89
|
const uri_1 = require("../../../util/vs/base/common/uri");
|
|
@@ -109,6 +108,9 @@ const systemMessages_1 = require("../common/systemMessages");
|
|
|
109
108
|
const tags_1 = require("../common/tags");
|
|
110
109
|
const terminalOutput_1 = require("../common/terminalOutput");
|
|
111
110
|
const xtabCurrentDocument_1 = require("../common/xtabCurrentDocument");
|
|
111
|
+
const cursorLineDivergence_1 = require("./cursorLineDivergence");
|
|
112
|
+
const editIntent_1 = require("./editIntent");
|
|
113
|
+
const responseFormatHandlers_1 = require("./responseFormatHandlers");
|
|
112
114
|
const xtabCustomDiffPatchResponseHandler_1 = require("./xtabCustomDiffPatchResponseHandler");
|
|
113
115
|
const xtabEndpoint_1 = require("./xtabEndpoint");
|
|
114
116
|
const xtabNextCursorPredictor_1 = require("./xtabNextCursorPredictor");
|
|
@@ -134,6 +136,28 @@ var RetryState;
|
|
|
134
136
|
}
|
|
135
137
|
RetryState.Retrying = Retrying;
|
|
136
138
|
})(RetryState || (RetryState = {}));
|
|
139
|
+
var FetchResult;
|
|
140
|
+
(function (FetchResult) {
|
|
141
|
+
class Lines {
|
|
142
|
+
constructor(linesStream, getFetchFailure, getResponseSoFar, fetchRequestStopWatch) {
|
|
143
|
+
this.linesStream = linesStream;
|
|
144
|
+
this.getFetchFailure = getFetchFailure;
|
|
145
|
+
this.getResponseSoFar = getResponseSoFar;
|
|
146
|
+
this.fetchRequestStopWatch = fetchRequestStopWatch;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
FetchResult.Lines = Lines;
|
|
150
|
+
class ModelNotFound {
|
|
151
|
+
static { this.INSTANCE = new ModelNotFound(); }
|
|
152
|
+
}
|
|
153
|
+
FetchResult.ModelNotFound = ModelNotFound;
|
|
154
|
+
class FetchFailure {
|
|
155
|
+
constructor(reason) {
|
|
156
|
+
this.reason = reason;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
FetchResult.FetchFailure = FetchFailure;
|
|
160
|
+
})(FetchResult || (FetchResult = {}));
|
|
137
161
|
let XtabProvider = class XtabProvider {
|
|
138
162
|
static { XtabProvider_1 = this; }
|
|
139
163
|
static { this.ID = configurationService_1.XTabProviderId; }
|
|
@@ -174,7 +198,8 @@ let XtabProvider = class XtabProvider {
|
|
|
174
198
|
return new statelessNextEditProvider_1.WithStatelessProviderTelemetry(noSuggestionReason, telemetry.build(result_1.Result.error(noSuggestionReason)));
|
|
175
199
|
}
|
|
176
200
|
const delaySession = this.userInteractionMonitor.createDelaySession(request.providerRequestStartDateTime);
|
|
177
|
-
const
|
|
201
|
+
const tracing = { tracer: logger, logContext, telemetry };
|
|
202
|
+
const iterator = this.doGetNextEdit(request, delaySession, tracing, cancellationToken, RetryState.NotRetrying.INSTANCE);
|
|
178
203
|
let res = await iterator.next(); // for-async-await loop doesn't work because we need to access the final return value
|
|
179
204
|
while (!res.done) {
|
|
180
205
|
yield new statelessNextEditProvider_1.WithStatelessProviderTelemetry(res.value, telemetry.build(result_1.Result.ok(undefined)));
|
|
@@ -195,29 +220,30 @@ let XtabProvider = class XtabProvider {
|
|
|
195
220
|
logContext.setProviderEndTime();
|
|
196
221
|
}
|
|
197
222
|
}
|
|
198
|
-
doGetNextEdit(request, delaySession,
|
|
199
|
-
return this.doGetNextEditWithSelection(request, (0, nearbyCursorInlineEditProvider_1.getOrDeduceSelectionFromLastEdit)(request.getActiveDocument()), delaySession,
|
|
223
|
+
doGetNextEdit(request, delaySession, tracing, cancellationToken, retryState) {
|
|
224
|
+
return this.doGetNextEditWithSelection(request, (0, nearbyCursorInlineEditProvider_1.getOrDeduceSelectionFromLastEdit)(request.getActiveDocument()), delaySession, tracing, cancellationToken, retryState);
|
|
200
225
|
}
|
|
201
|
-
async *doGetNextEditWithSelection(request, selection, delaySession,
|
|
226
|
+
async *doGetNextEditWithSelection(request, selection, delaySession, tracing, cancellationToken, retryState,
|
|
202
227
|
/**
|
|
203
228
|
* For cursor jump scenarios, this is the edit window around the original cursor position
|
|
204
229
|
* (before the jump). When provided, yielded edits will include this as `originalWindow`
|
|
205
230
|
* so the cache can serve the edit when the cursor is in either location.
|
|
206
231
|
*/
|
|
207
232
|
originalEditWindow) {
|
|
208
|
-
const tracer =
|
|
233
|
+
const tracer = tracing.tracer.createSubLogger(['XtabProvider', 'doGetNextEditWithSelection']);
|
|
234
|
+
const { logContext, telemetry } = tracing;
|
|
209
235
|
const activeDocument = request.getActiveDocument();
|
|
210
236
|
if (selection === null) {
|
|
211
237
|
return new statelessNextEditProvider_1.NoNextEditReason.Uncategorized(new Error('NoSelection'));
|
|
212
238
|
}
|
|
213
239
|
const { promptOptions, modelServiceConfig } = this.determineModelConfiguration(activeDocument);
|
|
214
|
-
|
|
215
|
-
const endpoint = this.getEndpointWithLogging(promptOptions.modelName, logContext,
|
|
240
|
+
telemetry.setModelConfig(JSON.stringify(modelServiceConfig));
|
|
241
|
+
const endpoint = this.getEndpointWithLogging(promptOptions.modelName, logContext, telemetry);
|
|
216
242
|
const cursorPosition = new position_1.Position(selection.endLineNumber, selection.endColumn);
|
|
217
243
|
const currentDocument = new xtabCurrentDocument_1.CurrentDocument(activeDocument.documentAfterEdits, cursorPosition);
|
|
218
|
-
this._configureDebounceTimings(request, currentDocument, promptOptions,
|
|
244
|
+
this._configureDebounceTimings(request, currentDocument, promptOptions, telemetry, delaySession, tracer);
|
|
219
245
|
const areaAroundEditWindowLinesRange = computeAreaAroundEditWindowLinesRange(currentDocument);
|
|
220
|
-
const editWindowLinesRange = this.computeEditWindowLinesRange(currentDocument, request, tracer,
|
|
246
|
+
const editWindowLinesRange = this.computeEditWindowLinesRange(currentDocument, request, tracer, telemetry);
|
|
221
247
|
const cursorOriginalLinesOffset = Math.max(0, currentDocument.cursorLineOffset - editWindowLinesRange.start);
|
|
222
248
|
const editWindowLastLineLength = currentDocument.transformer.getLineLength(editWindowLinesRange.endExclusive);
|
|
223
249
|
const editWindow = currentDocument.transformer.getOffsetRange(new range_1.Range(editWindowLinesRange.start + 1, 1, editWindowLinesRange.endExclusive, editWindowLastLineLength + 1));
|
|
@@ -242,25 +268,25 @@ let XtabProvider = class XtabProvider {
|
|
|
242
268
|
return new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('currentFile');
|
|
243
269
|
}
|
|
244
270
|
const { clippedTaggedCurrentDoc, areaAroundCodeToEdit } = taggedCurrentFileContentResult.val;
|
|
245
|
-
|
|
271
|
+
telemetry.setNLinesOfCurrentFileInPrompt(clippedTaggedCurrentDoc.lines.length);
|
|
246
272
|
const { aggressivenessLevel, userHappinessScore } = this.userInteractionMonitor.getAggressivenessLevel();
|
|
247
273
|
// Log user's raw aggressiveness setting when explicitly changed from default
|
|
248
274
|
const userAggressivenessSetting = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.Advanced.InlineEditsAggressiveness, this.expService);
|
|
249
|
-
|
|
275
|
+
telemetry.setUserAggressivenessSetting(userAggressivenessSetting);
|
|
250
276
|
// Log aggressiveness level and user happiness score
|
|
251
|
-
|
|
277
|
+
telemetry.setXtabAggressivenessLevel(aggressivenessLevel);
|
|
252
278
|
if (userHappinessScore !== undefined) {
|
|
253
|
-
|
|
279
|
+
telemetry.setXtabUserHappinessScore(userHappinessScore);
|
|
254
280
|
}
|
|
255
|
-
const langCtx = await this.getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, tracer, logContext, cancellationToken);
|
|
281
|
+
const langCtx = await this.getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, { tracer, logContext, telemetry }, cancellationToken);
|
|
256
282
|
if (cancellationToken.isCancellationRequested) {
|
|
257
283
|
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterLanguageContextAwait');
|
|
258
284
|
}
|
|
259
285
|
const lintErrors = new lintErrors_1.LintErrors(activeDocument.id, currentDocument, this.langDiagService, request.xtabEditHistory);
|
|
260
286
|
const promptPieces = new promptCrafting_1.PromptPieces(currentDocument, editWindowLinesRange, areaAroundEditWindowLinesRange, activeDocument, request.xtabEditHistory, clippedTaggedCurrentDoc.lines, areaAroundCodeToEdit, langCtx, aggressivenessLevel, lintErrors, XtabProvider_1.computeTokens, promptOptions);
|
|
261
287
|
const { prompt: userPrompt, nDiffsInPrompt, diffTokensInPrompt } = (0, promptCrafting_1.getUserPrompt)(promptPieces);
|
|
262
|
-
|
|
263
|
-
|
|
288
|
+
telemetry.setNDiffsInPrompt(nDiffsInPrompt);
|
|
289
|
+
telemetry.setDiffTokensInPrompt(diffTokensInPrompt);
|
|
264
290
|
const responseFormat = xtabPromptOptions.ResponseFormat.fromPromptingStrategy(promptOptions.promptingStrategy);
|
|
265
291
|
const prediction = this.getPredictedOutput(activeDocument, editWindowLines, responseFormat);
|
|
266
292
|
const messages = (0, xtabUtils_1.constructMessages)({
|
|
@@ -268,35 +294,47 @@ let XtabProvider = class XtabProvider {
|
|
|
268
294
|
userMsg: userPrompt,
|
|
269
295
|
});
|
|
270
296
|
logContext.setPrompt(messages);
|
|
271
|
-
|
|
297
|
+
telemetry.setPrompt(messages);
|
|
272
298
|
const HARD_CHAR_LIMIT = 30000 * 4; // 30K tokens, assuming 4 chars per token -- we use approximation here because counting tokens exactly is time-consuming
|
|
273
299
|
const promptCharCount = (0, xtabUtils_1.charCount)(messages);
|
|
274
300
|
if (promptCharCount > HARD_CHAR_LIMIT) {
|
|
275
301
|
return new statelessNextEditProvider_1.NoNextEditReason.PromptTooLarge('final');
|
|
276
302
|
}
|
|
277
|
-
await this.debounce(delaySession, retryState, tracer,
|
|
303
|
+
await this.debounce(delaySession, retryState, tracer, telemetry, cancellationToken);
|
|
278
304
|
if (cancellationToken.isCancellationRequested) {
|
|
279
305
|
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterDebounce');
|
|
280
306
|
}
|
|
281
307
|
// Fire-and-forget: collect lint errors and terminal output for telemetry in background to avoid blocking the main path
|
|
282
308
|
Promise.resolve().then(() => {
|
|
283
309
|
const lintErrorsData = lintErrors.getData();
|
|
284
|
-
|
|
310
|
+
telemetry.setLintErrors(lintErrorsData);
|
|
285
311
|
logContext.setDiagnosticsData(lintErrorsData);
|
|
286
312
|
const terminalOutputData = this.terminalMonitor.getData();
|
|
287
|
-
|
|
313
|
+
telemetry.setTerminalOutput(terminalOutputData);
|
|
288
314
|
logContext.setTerminalData(terminalOutputData);
|
|
289
315
|
});
|
|
290
316
|
// Fire-and-forget: compute GhostText-style similar files context for telemetry
|
|
291
|
-
|
|
317
|
+
telemetry.setSimilarFilesContext(this.similarFilesContextService.compute(activeDocument.id.uri, activeDocument.languageId, activeDocument.documentAfterEdits.value, currentDocument.cursorOffset));
|
|
292
318
|
request.fetchIssued = true;
|
|
293
|
-
|
|
319
|
+
const editStreamCtx = {
|
|
320
|
+
endpoint,
|
|
321
|
+
modelServiceConfig,
|
|
322
|
+
messages,
|
|
323
|
+
clippedTaggedCurrentDoc,
|
|
324
|
+
editWindowInfo: {
|
|
325
|
+
editWindow,
|
|
326
|
+
editWindowLines,
|
|
327
|
+
cursorOriginalLinesOffset,
|
|
328
|
+
editWindowLineRange: editWindowLinesRange,
|
|
329
|
+
},
|
|
330
|
+
promptPieces,
|
|
331
|
+
prediction,
|
|
332
|
+
originalEditWindow,
|
|
333
|
+
};
|
|
334
|
+
return yield* this.streamEditsWithFiltering(request, editStreamCtx, {
|
|
294
335
|
shouldRemoveCursorTagFromResponse,
|
|
295
336
|
responseFormat,
|
|
296
|
-
|
|
297
|
-
aggressivenessLevel,
|
|
298
|
-
userHappinessScore,
|
|
299
|
-
}, delaySession, tracer, telemetryBuilder, logContext, cancellationToken, originalEditWindow);
|
|
337
|
+
}, { aggressivenessLevel, userHappinessScore }, retryState, delaySession, { tracer, logContext, telemetry }, cancellationToken);
|
|
300
338
|
}
|
|
301
339
|
_configureDebounceTimings(request, currentDocument, promptOptions, telemetry, delaySession, tracer) {
|
|
302
340
|
const isCursorAtEndOfLine = currentDocument.isCursorAtEndOfLine();
|
|
@@ -356,17 +394,17 @@ let XtabProvider = class XtabProvider {
|
|
|
356
394
|
tracer.trace(`Aggressiveness ${userAggressiveness}: min response time set to ${minResponseTimeMs}ms`);
|
|
357
395
|
}
|
|
358
396
|
}
|
|
359
|
-
getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions,
|
|
397
|
+
getAndProcessLanguageContext(request, delaySession, activeDocument, cursorPosition, promptOptions, tracing, cancellationToken) {
|
|
360
398
|
const recordingEnabled = this.configService.getConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsLogContextRecorderEnabled);
|
|
361
399
|
if (!promptOptions.languageContext.enabled && !recordingEnabled) {
|
|
362
400
|
return Promise.resolve(undefined);
|
|
363
401
|
}
|
|
364
|
-
const langCtxPromise = this.getLanguageContext(request, delaySession, activeDocument, cursorPosition,
|
|
402
|
+
const langCtxPromise = this.getLanguageContext(request, delaySession, activeDocument, cursorPosition, tracing, cancellationToken);
|
|
365
403
|
// if recording, add diagnostics for the file to the recording and hook up the language context promise to write to the recording
|
|
366
404
|
if (recordingEnabled) {
|
|
367
405
|
langCtxPromise.then(langCtxs => {
|
|
368
406
|
if (langCtxs) {
|
|
369
|
-
logContext.setLanguageContext(langCtxs);
|
|
407
|
+
tracing.logContext.setLanguageContext(langCtxs);
|
|
370
408
|
}
|
|
371
409
|
});
|
|
372
410
|
}
|
|
@@ -374,7 +412,7 @@ let XtabProvider = class XtabProvider {
|
|
|
374
412
|
? langCtxPromise
|
|
375
413
|
: Promise.resolve(undefined);
|
|
376
414
|
}
|
|
377
|
-
async getLanguageContext(request, delaySession, activeDocument, cursorPosition,
|
|
415
|
+
async getLanguageContext(request, delaySession, activeDocument, cursorPosition, tracing, cancellationToken) {
|
|
378
416
|
try {
|
|
379
417
|
const textDoc = this.workspaceService.textDocuments.find(doc => doc.uri.toString() === activeDocument.id.uri);
|
|
380
418
|
if (textDoc === undefined) {
|
|
@@ -434,14 +472,15 @@ let XtabProvider = class XtabProvider {
|
|
|
434
472
|
return { start, end, items: langCtxItems };
|
|
435
473
|
}
|
|
436
474
|
catch (error) {
|
|
437
|
-
logContext.setError(errors_1.ErrorUtils.fromUnknown(error));
|
|
438
|
-
tracer.trace(`Failed to fetch language context: ${error}`);
|
|
475
|
+
tracing.logContext.setError(errors_1.ErrorUtils.fromUnknown(error));
|
|
476
|
+
tracing.tracer.trace(`Failed to fetch language context: ${error}`);
|
|
439
477
|
return undefined;
|
|
440
478
|
}
|
|
441
479
|
}
|
|
442
|
-
async *streamEditsWithFiltering(request,
|
|
443
|
-
const tracer =
|
|
444
|
-
const
|
|
480
|
+
async *streamEditsWithFiltering(request, editStreamCtx, responseOpts, fetchMetadata, retryState, delaySession, tracing, cancellationToken) {
|
|
481
|
+
const tracer = tracing.tracer.createSubLogger('streamEditsWithFiltering');
|
|
482
|
+
const subTracing = { ...tracing, tracer };
|
|
483
|
+
const iterator = this.streamEdits(request, editStreamCtx, responseOpts, fetchMetadata, retryState, delaySession, subTracing, cancellationToken);
|
|
445
484
|
let nEdits = 0;
|
|
446
485
|
let r = await iterator.next();
|
|
447
486
|
while (!r.done) {
|
|
@@ -461,13 +500,35 @@ let XtabProvider = class XtabProvider {
|
|
|
461
500
|
if (nEdits === 0 &&
|
|
462
501
|
r.value instanceof statelessNextEditProvider_1.NoNextEditReason.NoSuggestions // only retry if there was no error, cancellation, etc.
|
|
463
502
|
) {
|
|
464
|
-
return yield* this.doGetNextEditsWithCursorJump(request,
|
|
503
|
+
return yield* this.doGetNextEditsWithCursorJump(request, editStreamCtx, delaySession, tracing, cancellationToken, retryState);
|
|
465
504
|
}
|
|
466
505
|
return r.value;
|
|
467
506
|
}
|
|
468
|
-
async *streamEdits(request,
|
|
469
|
-
const tracer =
|
|
470
|
-
|
|
507
|
+
async *streamEdits(request, editStreamCtx, responseOpts, fetchMetadata, retryState, delaySession, tracing, cancellationToken) {
|
|
508
|
+
const tracer = tracing.tracer.createSubLogger('streamEdits');
|
|
509
|
+
// Create a local cancellation source linked to the caller's token.
|
|
510
|
+
// This lets us cancel the fetch immediately on cursor-line divergence
|
|
511
|
+
// without reaching into the request's CancellationTokenSource (which
|
|
512
|
+
// is owned by nextEditProvider.ts).
|
|
513
|
+
const fetchCts = new cancellation_1.CancellationTokenSource(cancellationToken);
|
|
514
|
+
const fetchCancellationToken = fetchCts.token;
|
|
515
|
+
try {
|
|
516
|
+
return yield* this._streamEditsImpl(request, editStreamCtx, responseOpts, fetchMetadata, retryState, delaySession, { ...tracing, tracer }, cancellationToken, fetchCts, fetchCancellationToken);
|
|
517
|
+
}
|
|
518
|
+
finally {
|
|
519
|
+
fetchCts.dispose();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Initiates the HTTP fetch, sets up the streaming pipeline, and returns either
|
|
524
|
+
* a clean line stream (with cursor-tag removal and latency logging applied)
|
|
525
|
+
* or an error / retry signal.
|
|
526
|
+
*
|
|
527
|
+
* This method encapsulates all fetch infrastructure so that downstream response
|
|
528
|
+
* format handlers only need an `AsyncIterable<string>` line stream.
|
|
529
|
+
*/
|
|
530
|
+
async _performFetch(endpoint, messages, prediction, requestId, fetchMetadata, shouldRemoveCursorTagFromResponse, editWindow, documentBeforeEdits, fetchCancellationToken, tracing) {
|
|
531
|
+
const { tracer, logContext, telemetry } = tracing;
|
|
471
532
|
const useFetcher = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.NextEditSuggestionsFetcher, this.expService) || undefined;
|
|
472
533
|
const fetchStreamSource = new chatMLFetcher_1.FetchStreamSource();
|
|
473
534
|
const fetchRequestStopWatch = new stopwatch_1.StopWatch();
|
|
@@ -475,8 +536,8 @@ let XtabProvider = class XtabProvider {
|
|
|
475
536
|
let chatResponseFailure;
|
|
476
537
|
let ttft;
|
|
477
538
|
const firstTokenReceived = new async_2.DeferredPromise();
|
|
478
|
-
logContext.setHeaderRequestId(
|
|
479
|
-
|
|
539
|
+
logContext.setHeaderRequestId(requestId);
|
|
540
|
+
telemetry.setFetchStartedAt();
|
|
480
541
|
logContext.setFetchStartTime();
|
|
481
542
|
// we must not await this promise because we want to stream edits as they come in
|
|
482
543
|
const fetchResultPromise = endpoint.makeChatRequest2({
|
|
@@ -504,30 +565,16 @@ let XtabProvider = class XtabProvider {
|
|
|
504
565
|
},
|
|
505
566
|
userInitiatedRequest: undefined,
|
|
506
567
|
telemetryProperties: {
|
|
507
|
-
requestId
|
|
568
|
+
requestId,
|
|
508
569
|
},
|
|
509
570
|
useFetcher,
|
|
510
571
|
customMetadata: {
|
|
511
|
-
aggressivenessLevel:
|
|
512
|
-
userHappinessScore:
|
|
572
|
+
aggressivenessLevel: fetchMetadata.aggressivenessLevel,
|
|
573
|
+
userHappinessScore: fetchMetadata.userHappinessScore,
|
|
513
574
|
},
|
|
514
|
-
},
|
|
515
|
-
|
|
575
|
+
}, fetchCancellationToken);
|
|
576
|
+
telemetry.setResponse(fetchResultPromise.then((response) => ({ response, ttft })));
|
|
516
577
|
logContext.setFullResponse(fetchResultPromise.then((response) => response.type === commonTypes_1.ChatFetchResponseType.Success ? response.value : undefined));
|
|
517
|
-
const fetchRes = await Promise.race([firstTokenReceived.p, fetchResultPromise]);
|
|
518
|
-
if (fetchRes && fetchRes.type !== commonTypes_1.ChatFetchResponseType.Success) {
|
|
519
|
-
if (fetchRes.type === commonTypes_1.ChatFetchResponseType.NotFound &&
|
|
520
|
-
!this.forceUseDefaultModel // if we haven't already forced using the default model; otherwise, this could cause an infinite loop
|
|
521
|
-
) {
|
|
522
|
-
this.forceUseDefaultModel = true;
|
|
523
|
-
return yield* this.doGetNextEdit(request, delaySession, tracer, logContext, cancellationToken, telemetryBuilder, opts.retryState); // use the same retry state
|
|
524
|
-
}
|
|
525
|
-
// diff-patch based model returns no choices if it has no edits to suggest
|
|
526
|
-
if (fetchRes.type === commonTypes_1.ChatFetchResponseType.Unknown && fetchRes.reason === commonTypes_1.RESPONSE_CONTAINED_NO_CHOICES) {
|
|
527
|
-
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
528
|
-
}
|
|
529
|
-
return mapChatFetcherErrorToNoNextEditReason(fetchRes);
|
|
530
|
-
}
|
|
531
578
|
fetchResultPromise
|
|
532
579
|
.then((response) => {
|
|
533
580
|
// this's a way to signal the edit-pushing code to know if the request failed and
|
|
@@ -546,6 +593,21 @@ let XtabProvider = class XtabProvider {
|
|
|
546
593
|
fetchStreamSource.resolve();
|
|
547
594
|
logContext.setResponse(responseSoFar);
|
|
548
595
|
});
|
|
596
|
+
const fetchRes = await Promise.race([firstTokenReceived.p, fetchResultPromise]);
|
|
597
|
+
if (fetchRes && fetchRes.type !== commonTypes_1.ChatFetchResponseType.Success) {
|
|
598
|
+
if (fetchRes.type === commonTypes_1.ChatFetchResponseType.NotFound &&
|
|
599
|
+
!this.forceUseDefaultModel // if we haven't already forced using the default model; otherwise, this could cause an infinite loop
|
|
600
|
+
) {
|
|
601
|
+
this.forceUseDefaultModel = true;
|
|
602
|
+
return FetchResult.ModelNotFound.INSTANCE;
|
|
603
|
+
}
|
|
604
|
+
// diff-patch based model returns no choices if it has no edits to suggest
|
|
605
|
+
if (fetchRes.type === commonTypes_1.ChatFetchResponseType.Unknown && fetchRes.reason === commonTypes_1.RESPONSE_CONTAINED_NO_CHOICES) {
|
|
606
|
+
return new FetchResult.FetchFailure(new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(documentBeforeEdits, editWindow));
|
|
607
|
+
}
|
|
608
|
+
return new FetchResult.FetchFailure(mapChatFetcherErrorToNoNextEditReason(fetchRes));
|
|
609
|
+
}
|
|
610
|
+
const getFetchFailure = () => chatResponseFailure ? mapChatFetcherErrorToNoNextEditReason(chatResponseFailure) : undefined;
|
|
549
611
|
const llmLinesStream = asyncIterableUtils_1.AsyncIterUtilsExt.splitLines(asyncIterableUtils_1.AsyncIterUtils.map(fetchStreamSource.stream, (chunk) => chunk.delta.text));
|
|
550
612
|
// logging of times
|
|
551
613
|
// removal of cursor tag if option is set
|
|
@@ -554,119 +616,150 @@ let XtabProvider = class XtabProvider {
|
|
|
554
616
|
for await (const v of llmLinesStream) {
|
|
555
617
|
const trace = `Line ${i++} emitted with latency ${fetchRequestStopWatch.elapsed()} ms`;
|
|
556
618
|
tracer.trace(trace);
|
|
557
|
-
yield
|
|
619
|
+
yield shouldRemoveCursorTagFromResponse
|
|
558
620
|
? v.replaceAll(tags_1.PromptTags.CURSOR, '')
|
|
559
621
|
: v;
|
|
560
622
|
}
|
|
561
623
|
})();
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
624
|
+
return new FetchResult.Lines(linesStream, getFetchFailure, () => responseSoFar, fetchRequestStopWatch);
|
|
625
|
+
}
|
|
626
|
+
async *_streamEditsImpl(request, editStreamCtx, responseOpts, fetchMetadata, retryState, delaySession, tracing, cancellationToken, fetchCts, fetchCancellationToken) {
|
|
627
|
+
const { tracer, logContext, telemetry } = tracing;
|
|
628
|
+
const { endpoint, messages, clippedTaggedCurrentDoc, editWindowInfo, promptPieces, prediction, originalEditWindow } = editStreamCtx;
|
|
629
|
+
const { editWindow, editWindowLines, cursorOriginalLinesOffset, editWindowLineRange } = editWindowInfo;
|
|
630
|
+
const targetDocument = request.getActiveDocument().id;
|
|
631
|
+
// Phase 1: Fetch lifecycle — initiate HTTP request and produce a clean line stream
|
|
632
|
+
const fetchResult = await this._performFetch(endpoint, messages, prediction, request.headerRequestId, fetchMetadata, responseOpts.shouldRemoveCursorTagFromResponse, editWindow, request.documentBeforeEdits, fetchCancellationToken, tracing);
|
|
633
|
+
if (fetchResult instanceof FetchResult.ModelNotFound) {
|
|
634
|
+
return yield* this.doGetNextEdit(request, delaySession, tracing, cancellationToken, retryState);
|
|
635
|
+
}
|
|
636
|
+
if (fetchResult instanceof FetchResult.FetchFailure) {
|
|
637
|
+
return fetchResult.reason;
|
|
638
|
+
}
|
|
639
|
+
const { linesStream, getFetchFailure, getResponseSoFar, fetchRequestStopWatch } = fetchResult;
|
|
640
|
+
// Phase 2: Dispatch to the appropriate response format handler
|
|
641
|
+
const isFromCursorJump = retryState instanceof RetryState.Retrying && retryState.reason === 'cursorJump';
|
|
642
|
+
let parseResult;
|
|
643
|
+
switch (responseOpts.responseFormat) {
|
|
644
|
+
case xtabPromptOptions.ResponseFormat.EditWindowOnly: {
|
|
645
|
+
parseResult = (0, responseFormatHandlers_1.handleEditWindowOnly)(linesStream);
|
|
646
|
+
break;
|
|
585
647
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const activeDoc = request.getActiveDocument();
|
|
590
|
-
const currentDocument = promptPieces.currentDocument;
|
|
591
|
-
const lastLine = currentDocument.lines[clippedTaggedCurrentDoc.keptRange.endExclusive - 1];
|
|
592
|
-
const lastLineLength = lastLine.length;
|
|
593
|
-
const pseudoEditWindow = currentDocument.transformer.getOffsetRange(new range_1.Range(clippedTaggedCurrentDoc.keptRange.start + 1, 1, clippedTaggedCurrentDoc.keptRange.endExclusive, lastLineLength + 1));
|
|
594
|
-
return yield* xtabCustomDiffPatchResponseHandler_1.XtabCustomDiffPatchResponseHandler.handleResponse(linesStream, currentDocument, activeDoc.id, activeDoc.workspaceRoot, pseudoEditWindow, tracer, () => chatResponseFailure ? mapChatFetcherErrorToNoNextEditReason(chatResponseFailure) : undefined);
|
|
595
|
-
}
|
|
596
|
-
else if (opts.responseFormat === xtabPromptOptions.ResponseFormat.UnifiedWithXml) {
|
|
597
|
-
const linesIter = linesStream[Symbol.asyncIterator]();
|
|
598
|
-
const firstLine = await linesIter.next();
|
|
599
|
-
if (chatResponseFailure !== undefined) { // handle fetch failure
|
|
600
|
-
return new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors_1.ErrorUtils.fromUnknown(chatResponseFailure));
|
|
648
|
+
case xtabPromptOptions.ResponseFormat.CodeBlock: {
|
|
649
|
+
parseResult = (0, responseFormatHandlers_1.handleCodeBlock)(linesStream);
|
|
650
|
+
break;
|
|
601
651
|
}
|
|
602
|
-
|
|
603
|
-
|
|
652
|
+
case xtabPromptOptions.ResponseFormat.EditWindowWithEditIntent:
|
|
653
|
+
case xtabPromptOptions.ResponseFormat.EditWindowWithEditIntentShort: {
|
|
654
|
+
const parseMode = responseOpts.responseFormat === xtabPromptOptions.ResponseFormat.EditWindowWithEditIntentShort
|
|
655
|
+
? editIntent_1.EditIntentParseMode.ShortName
|
|
656
|
+
: editIntent_1.EditIntentParseMode.Tags;
|
|
657
|
+
parseResult = await (0, responseFormatHandlers_1.handleEditWindowWithEditIntent)(linesStream, tracer, parseMode, getFetchFailure);
|
|
658
|
+
break;
|
|
604
659
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
660
|
+
case xtabPromptOptions.ResponseFormat.CustomDiffPatch: {
|
|
661
|
+
const activeDoc = request.getActiveDocument();
|
|
662
|
+
const currentDocument = promptPieces.currentDocument;
|
|
663
|
+
const lastLine = currentDocument.lines[clippedTaggedCurrentDoc.keptRange.endExclusive - 1];
|
|
664
|
+
const lastLineLength = lastLine.length;
|
|
665
|
+
const pseudoEditWindow = currentDocument.transformer.getOffsetRange(new range_1.Range(clippedTaggedCurrentDoc.keptRange.start + 1, 1, clippedTaggedCurrentDoc.keptRange.endExclusive, lastLineLength + 1));
|
|
666
|
+
parseResult = new responseFormatHandlers_1.ResponseParseResult.DirectEdits(xtabCustomDiffPatchResponseHandler_1.XtabCustomDiffPatchResponseHandler.handleResponse(linesStream, currentDocument, activeDoc.id, activeDoc.workspaceRoot, pseudoEditWindow, tracer, getFetchFailure));
|
|
667
|
+
break;
|
|
608
668
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
const lines = [];
|
|
618
|
-
let v = await linesIter.next();
|
|
619
|
-
while (!v.done) {
|
|
620
|
-
if (v.value.includes(tags_1.ResponseTags.INSERT.end)) {
|
|
621
|
-
break;
|
|
622
|
-
}
|
|
623
|
-
else {
|
|
624
|
-
lines.push(v.value);
|
|
625
|
-
}
|
|
626
|
-
v = await linesIter.next();
|
|
627
|
-
}
|
|
628
|
-
const line = editWindowLineRange.start + cursorOriginalLinesOffset + 2;
|
|
629
|
-
yield {
|
|
630
|
-
edit: new lineEdit_1.LineReplacement(new lineRange_1.LineRange(line, line), lines),
|
|
631
|
-
isFromCursorJump,
|
|
632
|
-
window: editWindow,
|
|
633
|
-
originalWindow: originalEditWindow,
|
|
669
|
+
case xtabPromptOptions.ResponseFormat.UnifiedWithXml: {
|
|
670
|
+
parseResult = await (0, responseFormatHandlers_1.handleUnifiedWithXml)(linesStream, {
|
|
671
|
+
editWindowLines,
|
|
672
|
+
editWindowLineRange,
|
|
673
|
+
cursorOriginalLinesOffset,
|
|
674
|
+
cursorColumnZeroBased: promptPieces.currentDocument.cursorPosition.column - 1,
|
|
675
|
+
editWindow,
|
|
676
|
+
originalEditWindow,
|
|
634
677
|
targetDocument,
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
if (trimmedLines === tags_1.ResponseTags.EDIT.start) {
|
|
639
|
-
cleanedLinesStream = (async function* () {
|
|
640
|
-
let v = await linesIter.next();
|
|
641
|
-
while (!v.done) {
|
|
642
|
-
if (v.value.includes(tags_1.ResponseTags.EDIT.end)) {
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
|
-
yield v.value;
|
|
646
|
-
v = await linesIter.next();
|
|
647
|
-
}
|
|
648
|
-
})();
|
|
649
|
-
}
|
|
650
|
-
else {
|
|
651
|
-
return new statelessNextEditProvider_1.NoNextEditReason.Unexpected(new Error(`unexpected tag ${trimmedLines}`));
|
|
678
|
+
isFromCursorJump,
|
|
679
|
+
}, request.documentBeforeEdits, tracer, getFetchFailure);
|
|
680
|
+
break;
|
|
652
681
|
}
|
|
682
|
+
default:
|
|
683
|
+
(0, assert_1.assertNever)(responseOpts.responseFormat);
|
|
653
684
|
}
|
|
654
|
-
|
|
655
|
-
|
|
685
|
+
// Handle result uniformly
|
|
686
|
+
if (parseResult instanceof responseFormatHandlers_1.ResponseParseResult.Done) {
|
|
687
|
+
return parseResult.reason;
|
|
656
688
|
}
|
|
657
|
-
|
|
658
|
-
|
|
689
|
+
if (parseResult instanceof responseFormatHandlers_1.ResponseParseResult.DirectEdits) {
|
|
690
|
+
return yield* parseResult.stream;
|
|
659
691
|
}
|
|
692
|
+
// parseResult is EditWindowLines — log edit-intent telemetry and apply aggressiveness filter
|
|
693
|
+
if (parseResult.editIntentMetadata) {
|
|
694
|
+
const { intent, parseError } = parseResult.editIntentMetadata;
|
|
695
|
+
telemetry.setEditIntent(intent);
|
|
696
|
+
if (parseError) {
|
|
697
|
+
telemetry.setEditIntentParseError(parseError);
|
|
698
|
+
}
|
|
699
|
+
if (!xtabPromptOptions.EditIntent.shouldShowEdit(intent, promptPieces.aggressivenessLevel)) {
|
|
700
|
+
tracer.trace(`Filtered out edit due to edit intent "${intent}" with aggressiveness "${promptPieces.aggressivenessLevel}"`);
|
|
701
|
+
return new statelessNextEditProvider_1.NoNextEditReason.FilteredOut(`editIntent:${intent} aggressivenessLevel:${promptPieces.aggressivenessLevel}`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
const cleanedLinesStream = parseResult.lines;
|
|
660
705
|
const diffOptions = {
|
|
661
706
|
emitFastCursorLineChange: responseProcessor_1.ResponseProcessor.mapEmitFastCursorLineChange(this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabProviderEmitFastCursorLineChange, this.expService)),
|
|
662
707
|
nLinesToConverge: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabNNonSignificantLinesToConverge, this.expService),
|
|
663
708
|
nSignificantLinesToConverge: this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabNSignificantLinesToConverge, this.expService),
|
|
664
709
|
};
|
|
665
710
|
tracer.trace(`starting to diff stream against edit window lines with latency ${fetchRequestStopWatch.elapsed()} ms`);
|
|
711
|
+
// Wrap the line stream to detect early cursor-line divergence.
|
|
712
|
+
// If the user has typed at the cursor since the request started and the cursor line
|
|
713
|
+
// in the model's response doesn't match what the user currently has, the response
|
|
714
|
+
// is stale and we can cancel early instead of waiting for the full response.
|
|
715
|
+
//
|
|
716
|
+
// We check compatibility using `isModelCursorLineCompatible`: the user's
|
|
717
|
+
// cursor-line change must be contained within the model's cursor-line change range
|
|
718
|
+
// and match via the helper's `startsWith` / auto-close subsequence rules.
|
|
719
|
+
const earlyCursorLineDivergenceCancellation = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabEarlyCursorLineDivergenceCancellation, this.expService);
|
|
720
|
+
let cursorLineDiverged = false;
|
|
721
|
+
const divergenceCheckedStream = earlyCursorLineDivergenceCancellation
|
|
722
|
+
? (async function* () {
|
|
723
|
+
let lineIdx = 0;
|
|
724
|
+
for await (const line of cleanedLinesStream) {
|
|
725
|
+
if (lineIdx === cursorOriginalLinesOffset) {
|
|
726
|
+
const intermediateEdit = request.intermediateUserEdit;
|
|
727
|
+
if (intermediateEdit && !intermediateEdit.isEmpty()) {
|
|
728
|
+
const cursorDocLineIdx = editWindowLineRange.start + cursorOriginalLinesOffset;
|
|
729
|
+
const currentCursorLine = (0, cursorLineDivergence_1.getCurrentCursorLine)(request.documentBeforeEdits.getTransformer(), cursorDocLineIdx, intermediateEdit);
|
|
730
|
+
if (currentCursorLine !== undefined) {
|
|
731
|
+
const originalCursorLine = editWindowLines[cursorOriginalLinesOffset];
|
|
732
|
+
if (currentCursorLine !== originalCursorLine // user changed the cursor line
|
|
733
|
+
&& !(0, cursorLineDivergence_1.isModelCursorLineCompatible)(originalCursorLine, currentCursorLine, line) // model's cursor line isn't compatible with user's typing
|
|
734
|
+
) {
|
|
735
|
+
cursorLineDiverged = true;
|
|
736
|
+
tracer.trace(`Cursor line DIVERGED: model="${line}" current="${currentCursorLine}"`);
|
|
737
|
+
// Cancel our local fetch token so the HTTP request is
|
|
738
|
+
// aborted immediately. We own this token, so this is safe.
|
|
739
|
+
fetchCts.cancel();
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
yield line;
|
|
746
|
+
lineIdx++;
|
|
747
|
+
}
|
|
748
|
+
})()
|
|
749
|
+
: cleanedLinesStream;
|
|
666
750
|
let i = 0;
|
|
667
751
|
let hasBeenDelayed = false;
|
|
668
752
|
try {
|
|
669
|
-
for await (const edit of responseProcessor_1.ResponseProcessor.diff(editWindowLines,
|
|
753
|
+
for await (const edit of responseProcessor_1.ResponseProcessor.diff(editWindowLines, divergenceCheckedStream, cursorOriginalLinesOffset, diffOptions)) {
|
|
754
|
+
if (cursorLineDiverged) {
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
{
|
|
758
|
+
const fetchFailure = getFetchFailure();
|
|
759
|
+
if (fetchFailure) {
|
|
760
|
+
return fetchFailure;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
670
763
|
tracer.trace(`ResponseProcessor streamed edit #${i} with latency ${fetchRequestStopWatch.elapsed()} ms`);
|
|
671
764
|
const singleLineEdits = [];
|
|
672
765
|
if (edit.lineRange.startLineNumber === edit.lineRange.endLineNumberExclusive || // we don't want to run diff on insertion
|
|
@@ -690,15 +783,12 @@ let XtabProvider = class XtabProvider {
|
|
|
690
783
|
singleLineEdits.push(singleLineEdit);
|
|
691
784
|
}
|
|
692
785
|
}
|
|
693
|
-
|
|
694
|
-
break;
|
|
695
|
-
}
|
|
696
|
-
logContext.setResponse(responseSoFar);
|
|
786
|
+
logContext.setResponse(getResponseSoFar());
|
|
697
787
|
for (const singleLineEdit of singleLineEdits) {
|
|
698
788
|
tracer.trace(`extracting edit #${i}: ${singleLineEdit.toString()}`);
|
|
699
789
|
if (!hasBeenDelayed) { // delay only the first one
|
|
700
790
|
hasBeenDelayed = true;
|
|
701
|
-
const artificialDelay = this.determineArtificialDelayMs(delaySession, tracer,
|
|
791
|
+
const artificialDelay = this.determineArtificialDelayMs(delaySession, tracer, telemetry);
|
|
702
792
|
if (artificialDelay) {
|
|
703
793
|
await (0, async_2.timeout)(artificialDelay);
|
|
704
794
|
tracer.trace(`Artificial delay of ${artificialDelay} ms completed`);
|
|
@@ -711,8 +801,14 @@ let XtabProvider = class XtabProvider {
|
|
|
711
801
|
i++;
|
|
712
802
|
}
|
|
713
803
|
}
|
|
714
|
-
if (
|
|
715
|
-
return
|
|
804
|
+
if (cursorLineDiverged) {
|
|
805
|
+
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('cursorLineDiverged');
|
|
806
|
+
}
|
|
807
|
+
{
|
|
808
|
+
const fetchFailure = getFetchFailure();
|
|
809
|
+
if (fetchFailure) {
|
|
810
|
+
return fetchFailure;
|
|
811
|
+
}
|
|
716
812
|
}
|
|
717
813
|
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
718
814
|
}
|
|
@@ -722,9 +818,11 @@ let XtabProvider = class XtabProvider {
|
|
|
722
818
|
return new statelessNextEditProvider_1.NoNextEditReason.Unexpected(errors_1.ErrorUtils.fromUnknown(err));
|
|
723
819
|
}
|
|
724
820
|
}
|
|
725
|
-
async *doGetNextEditsWithCursorJump(request,
|
|
821
|
+
async *doGetNextEditsWithCursorJump(request, editStreamCtx, delaySession, tracing, cancellationToken, retryState) {
|
|
822
|
+
const { tracer, telemetry } = tracing;
|
|
823
|
+
const { editWindowInfo: { editWindow }, modelServiceConfig, promptPieces } = editStreamCtx;
|
|
726
824
|
const noSuggestions = new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
727
|
-
const nextCursorLinePrediction = this.nextCursorPredictor.determineEnablement(
|
|
825
|
+
const nextCursorLinePrediction = this.nextCursorPredictor.determineEnablement(modelServiceConfig.supportsNextCursorLinePrediction);
|
|
728
826
|
if (nextCursorLinePrediction === undefined || retryState instanceof RetryState.Retrying) {
|
|
729
827
|
return noSuggestions;
|
|
730
828
|
}
|
|
@@ -732,7 +830,7 @@ let XtabProvider = class XtabProvider {
|
|
|
732
830
|
tracer.trace('Skipping cursor prediction: user typed during request');
|
|
733
831
|
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('beforeNextCursorPredictionFetchUserTyped');
|
|
734
832
|
}
|
|
735
|
-
const nextCursorLineR = await this.nextCursorPredictor.predictNextCursorPosition(promptPieces, tracer,
|
|
833
|
+
const nextCursorLineR = await this.nextCursorPredictor.predictNextCursorPosition(promptPieces, tracer, telemetry, cancellationToken);
|
|
736
834
|
if (cancellationToken.isCancellationRequested) {
|
|
737
835
|
return new statelessNextEditProvider_1.NoNextEditReason.GotCancelled('afterNextCursorPredictionFetch');
|
|
738
836
|
}
|
|
@@ -742,26 +840,26 @@ let XtabProvider = class XtabProvider {
|
|
|
742
840
|
}
|
|
743
841
|
if (nextCursorLineR.isError()) {
|
|
744
842
|
tracer.trace(`Predicted next cursor line error: ${nextCursorLineR.err.message}`);
|
|
745
|
-
|
|
843
|
+
telemetry.setNextCursorLineError(nextCursorLineR.err.message);
|
|
746
844
|
return noSuggestions;
|
|
747
845
|
}
|
|
748
846
|
const prediction = nextCursorLineR.val;
|
|
749
847
|
if (prediction.kind === 'differentFile') {
|
|
750
|
-
return yield* this.handleCrossFilePrediction(prediction, nextCursorLinePrediction, request,
|
|
848
|
+
return yield* this.handleCrossFilePrediction(prediction, nextCursorLinePrediction, request, editStreamCtx, delaySession, tracing, cancellationToken);
|
|
751
849
|
}
|
|
752
850
|
const nextCursorLineZeroBased = prediction.lineNumber;
|
|
753
851
|
const lineDistanceFromCursorLine = nextCursorLineZeroBased - promptPieces.currentDocument.cursorLineOffset;
|
|
754
|
-
|
|
755
|
-
|
|
852
|
+
telemetry.setNextCursorLineDistance(lineDistanceFromCursorLine);
|
|
853
|
+
telemetry.setNextCursorIsCrossFile(false);
|
|
756
854
|
tracer.trace(`Predicted next cursor line: ${nextCursorLineZeroBased}`);
|
|
757
855
|
if (nextCursorLineZeroBased >= promptPieces.currentDocument.lines.length) { // >= because the line index is zero-based
|
|
758
856
|
tracer.trace(`Predicted next cursor line error: exceedsDocumentLines`);
|
|
759
|
-
|
|
857
|
+
telemetry.setNextCursorLineError('exceedsDocumentLines');
|
|
760
858
|
return noSuggestions;
|
|
761
859
|
}
|
|
762
860
|
if (promptPieces.editWindowLinesRange.contains(nextCursorLineZeroBased)) {
|
|
763
861
|
tracer.trace(`Predicted next cursor line error: withinEditWindow`);
|
|
764
|
-
|
|
862
|
+
telemetry.setNextCursorLineError('withinEditWindow');
|
|
765
863
|
return noSuggestions;
|
|
766
864
|
}
|
|
767
865
|
const nextCursorLineOneBased = nextCursorLineZeroBased + 1;
|
|
@@ -774,7 +872,7 @@ let XtabProvider = class XtabProvider {
|
|
|
774
872
|
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow, nextCursorPosition);
|
|
775
873
|
}
|
|
776
874
|
case nextCursorLinePrediction_1.NextCursorLinePrediction.OnlyWithEdit: {
|
|
777
|
-
const v = this.doGetNextEditWithSelection(request, new range_1.Range(nextCursorLineOneBased, nextCursorColumn, nextCursorLineOneBased, nextCursorColumn), delaySession,
|
|
875
|
+
const v = this.doGetNextEditWithSelection(request, new range_1.Range(nextCursorLineOneBased, nextCursorColumn, nextCursorLineOneBased, nextCursorColumn), delaySession, tracing, cancellationToken, new RetryState.Retrying('cursorJump'), editWindow);
|
|
778
876
|
return yield* v;
|
|
779
877
|
}
|
|
780
878
|
default: {
|
|
@@ -782,11 +880,13 @@ let XtabProvider = class XtabProvider {
|
|
|
782
880
|
}
|
|
783
881
|
}
|
|
784
882
|
}
|
|
785
|
-
async *handleCrossFilePrediction(prediction, nextCursorLinePrediction, request,
|
|
883
|
+
async *handleCrossFilePrediction(prediction, nextCursorLinePrediction, request, editStreamCtx, delaySession, tracing, cancellationToken) {
|
|
884
|
+
const { tracer, telemetry } = tracing;
|
|
885
|
+
const { editWindowInfo: { editWindow }, promptPieces } = editStreamCtx;
|
|
786
886
|
const workspaceRoot = promptPieces.activeDoc.workspaceRoot;
|
|
787
887
|
if (!workspaceRoot && !(0, path_1.isAbsolute)(prediction.filePath)) {
|
|
788
888
|
tracer.trace('Predicted cross-file cursor jump error: noWorkspaceRoot');
|
|
789
|
-
|
|
889
|
+
telemetry.setNextCursorLineError('crossFile:noWorkspaceRoot');
|
|
790
890
|
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow);
|
|
791
891
|
}
|
|
792
892
|
const targetUri = (0, path_1.isAbsolute)(prediction.filePath)
|
|
@@ -795,7 +895,7 @@ let XtabProvider = class XtabProvider {
|
|
|
795
895
|
const targetDocumentId = documentId_1.DocumentId.create(targetUri.toString());
|
|
796
896
|
const nextCursorLineOneBased = prediction.lineNumber + 1;
|
|
797
897
|
const nextCursorPosition = new position_1.Position(nextCursorLineOneBased, 1);
|
|
798
|
-
|
|
898
|
+
telemetry.setNextCursorIsCrossFile(true);
|
|
799
899
|
tracer.trace(`Predicted cross-file cursor jump: ${prediction.filePath}:${prediction.lineNumber}`);
|
|
800
900
|
switch (nextCursorLinePrediction) {
|
|
801
901
|
case nextCursorLinePrediction_1.NextCursorLinePrediction.Jump: {
|
|
@@ -808,7 +908,7 @@ let XtabProvider = class XtabProvider {
|
|
|
808
908
|
}
|
|
809
909
|
catch (err) {
|
|
810
910
|
tracer.trace(`Failed to open target file for cross-file edit: ${errors_1.ErrorUtils.fromUnknown(err).message}`);
|
|
811
|
-
|
|
911
|
+
telemetry.setNextCursorLineError('crossFile:failedToOpenFile');
|
|
812
912
|
return new statelessNextEditProvider_1.NoNextEditReason.NoSuggestions(request.documentBeforeEdits, editWindow, nextCursorPosition, targetDocumentId);
|
|
813
913
|
}
|
|
814
914
|
if (cancellationToken.isCancellationRequested) {
|
|
@@ -821,7 +921,7 @@ let XtabProvider = class XtabProvider {
|
|
|
821
921
|
const targetContent = new abstractText_1.StringText(targetTextDoc.getText());
|
|
822
922
|
const syntheticDoc = new statelessNextEditProvider_1.StatelessNextEditDocument(targetDocumentId, promptPieces.activeDoc.workspaceRoot, languageId_1.LanguageId.create(targetTextDoc.languageId), targetContent.getLines(), lineEdit_1.LineEdit.empty, targetContent, new edit_1.Edits(stringEdit_1.StringEdit, []));
|
|
823
923
|
const syntheticRequest = new statelessNextEditProvider_1.StatelessNextEditRequest(request.headerRequestId, request.opportunityId, targetContent, [syntheticDoc], 0, request.xtabEditHistory, new async_2.DeferredPromise(), request.expandedEditWindowNLines, request.isSpeculative, request.logContext, request.recordingBookmark, request.recording, request.providerRequestStartDateTime);
|
|
824
|
-
return yield* this.doGetNextEditWithSelection(syntheticRequest, new range_1.Range(nextCursorLineOneBased, 1, nextCursorLineOneBased, 1), delaySession,
|
|
924
|
+
return yield* this.doGetNextEditWithSelection(syntheticRequest, new range_1.Range(nextCursorLineOneBased, 1, nextCursorLineOneBased, 1), delaySession, tracing, cancellationToken, new RetryState.Retrying('cursorJump'), editWindow);
|
|
825
925
|
}
|
|
826
926
|
default: {
|
|
827
927
|
(0, assert_1.assertNever)(nextCursorLinePrediction);
|
|
@@ -873,7 +973,7 @@ let XtabProvider = class XtabProvider {
|
|
|
873
973
|
const maxMergeConflictLines = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabMaxMergeConflictLines, this.expService);
|
|
874
974
|
if (maxMergeConflictLines) {
|
|
875
975
|
const tentativeEditWindow = new offsetRange_1.OffsetRange(codeToEditStart, codeToEditEndExcl);
|
|
876
|
-
const mergeConflictRange = findMergeConflictMarkersRange(currentDocLines, tentativeEditWindow, maxMergeConflictLines);
|
|
976
|
+
const mergeConflictRange = (0, xtabUtils_1.findMergeConflictMarkersRange)(currentDocLines, tentativeEditWindow, maxMergeConflictLines);
|
|
877
977
|
if (mergeConflictRange) {
|
|
878
978
|
const onlyMergeConflictLines = this.configService.getExperimentBasedConfig(configurationService_1.ConfigKey.TeamInternal.InlineEditsXtabOnlyMergeConflictLines, this.expService);
|
|
879
979
|
telemetry.setMergeConflictExpanded(onlyMergeConflictLines ? 'only' : 'normal');
|
|
@@ -1191,176 +1291,4 @@ function getPredictionContents(doc, editWindowLines, responseFormat) {
|
|
|
1191
1291
|
(0, assert_1.assertNever)(responseFormat);
|
|
1192
1292
|
}
|
|
1193
1293
|
}
|
|
1194
|
-
/**
|
|
1195
|
-
* Mode for parsing edit intent from the model response.
|
|
1196
|
-
*/
|
|
1197
|
-
var EditIntentParseMode;
|
|
1198
|
-
(function (EditIntentParseMode) {
|
|
1199
|
-
/** Parse using XML-style tags: <|edit_intent|>value<|/edit_intent|> */
|
|
1200
|
-
EditIntentParseMode["Tags"] = "tags";
|
|
1201
|
-
/** Parse using short names on the first line: N|L|M|H */
|
|
1202
|
-
EditIntentParseMode["ShortName"] = "shortName";
|
|
1203
|
-
})(EditIntentParseMode || (exports.EditIntentParseMode = EditIntentParseMode = {}));
|
|
1204
|
-
/**
|
|
1205
|
-
* Parses the edit_intent from the first line of the response stream.
|
|
1206
|
-
* The edit_intent MUST be on the first line, otherwise it's treated as not provided.
|
|
1207
|
-
* Returns the parsed EditIntent and a new stream with the remaining content.
|
|
1208
|
-
*
|
|
1209
|
-
* Supports two modes:
|
|
1210
|
-
* - Tags (default): <|edit_intent|>low|medium|high|no_edit<|/edit_intent|>
|
|
1211
|
-
* - ShortName: N|L|M|H on the first line
|
|
1212
|
-
*
|
|
1213
|
-
* @param linesStream The stream of lines from the model response
|
|
1214
|
-
* @param tracer Logger for tracing
|
|
1215
|
-
* @param mode The parse mode (Tags or ShortName), defaults to Tags
|
|
1216
|
-
*/
|
|
1217
|
-
async function parseEditIntentFromStream(linesStream, tracer, mode = EditIntentParseMode.Tags) {
|
|
1218
|
-
if (mode === EditIntentParseMode.ShortName) {
|
|
1219
|
-
return parseEditIntentFromStreamShortName(linesStream, tracer);
|
|
1220
|
-
}
|
|
1221
|
-
return parseEditIntentFromStreamTags(linesStream, tracer);
|
|
1222
|
-
}
|
|
1223
|
-
/**
|
|
1224
|
-
* Parses the edit_intent using short name format (N|L|M|H on first line).
|
|
1225
|
-
*/
|
|
1226
|
-
async function parseEditIntentFromStreamShortName(linesStream, tracer) {
|
|
1227
|
-
let editIntent = xtabPromptOptions.EditIntent.High; // Default to high (always show) if no short name found
|
|
1228
|
-
let parseError;
|
|
1229
|
-
const linesIter = linesStream[Symbol.asyncIterator]();
|
|
1230
|
-
const firstLineResult = await linesIter.next();
|
|
1231
|
-
if (firstLineResult.done) {
|
|
1232
|
-
// Empty stream
|
|
1233
|
-
parseError = 'emptyResponse';
|
|
1234
|
-
tracer.warn(`Empty response stream, no edit_intent short name found`);
|
|
1235
|
-
const remainingLinesStream = (async function* () { })();
|
|
1236
|
-
return { editIntent, remainingLinesStream, parseError };
|
|
1237
|
-
}
|
|
1238
|
-
const firstLine = firstLineResult.value.trim();
|
|
1239
|
-
// Check if the first line is a single character short name
|
|
1240
|
-
const parsedIntent = xtabPromptOptions.EditIntent.fromShortName(firstLine);
|
|
1241
|
-
if (parsedIntent !== undefined) {
|
|
1242
|
-
editIntent = parsedIntent;
|
|
1243
|
-
tracer.trace(`Parsed edit_intent short name from first line: "${firstLine}" -> ${editIntent}`);
|
|
1244
|
-
// Create a new stream with the remaining lines (excluding the short name line)
|
|
1245
|
-
const remainingLinesStream = (async function* () {
|
|
1246
|
-
let next = await linesIter.next();
|
|
1247
|
-
while (!next.done) {
|
|
1248
|
-
yield next.value;
|
|
1249
|
-
next = await linesIter.next();
|
|
1250
|
-
}
|
|
1251
|
-
})();
|
|
1252
|
-
return { editIntent, remainingLinesStream, parseError };
|
|
1253
|
-
}
|
|
1254
|
-
// Short name not found or invalid
|
|
1255
|
-
parseError = `unknownIntentValue:${firstLine}`;
|
|
1256
|
-
tracer.warn(`Edit intent parse error: ${parseError} (using Xtab275EditIntentShort prompting strategy). ` +
|
|
1257
|
-
`Defaulting to High (always show). First line was: "${firstLine.substring(0, 100)}..."`);
|
|
1258
|
-
// Return the first line plus the rest of the stream
|
|
1259
|
-
const remainingLinesStream = (async function* () {
|
|
1260
|
-
yield firstLineResult.value; // Use original value, not trimmed
|
|
1261
|
-
let next = await linesIter.next();
|
|
1262
|
-
while (!next.done) {
|
|
1263
|
-
yield next.value;
|
|
1264
|
-
next = await linesIter.next();
|
|
1265
|
-
}
|
|
1266
|
-
})();
|
|
1267
|
-
return { editIntent, remainingLinesStream, parseError };
|
|
1268
|
-
}
|
|
1269
|
-
/**
|
|
1270
|
-
* Parses the edit_intent tag from the first line of the response stream (original tag-based format).
|
|
1271
|
-
*/
|
|
1272
|
-
async function parseEditIntentFromStreamTags(linesStream, tracer) {
|
|
1273
|
-
const EDIT_INTENT_START_TAG = '<|edit_intent|>';
|
|
1274
|
-
const EDIT_INTENT_END_TAG = '<|/edit_intent|>';
|
|
1275
|
-
let editIntent = xtabPromptOptions.EditIntent.High; // Default to high (always show) if no tag found
|
|
1276
|
-
let parseError;
|
|
1277
|
-
const linesIter = linesStream[Symbol.asyncIterator]();
|
|
1278
|
-
const firstLineResult = await linesIter.next();
|
|
1279
|
-
if (firstLineResult.done) {
|
|
1280
|
-
// Empty stream
|
|
1281
|
-
parseError = 'emptyResponse';
|
|
1282
|
-
tracer.warn(`Empty response stream, no edit_intent tag found`);
|
|
1283
|
-
const remainingLinesStream = (async function* () { })();
|
|
1284
|
-
return { editIntent, remainingLinesStream, parseError };
|
|
1285
|
-
}
|
|
1286
|
-
const firstLine = firstLineResult.value;
|
|
1287
|
-
// Check if the first line contains the complete edit_intent tag
|
|
1288
|
-
const startIdx = firstLine.indexOf(EDIT_INTENT_START_TAG);
|
|
1289
|
-
const endIdx = firstLine.indexOf(EDIT_INTENT_END_TAG);
|
|
1290
|
-
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
1291
|
-
// Found complete tag on first line
|
|
1292
|
-
const intentValue = firstLine.substring(startIdx + EDIT_INTENT_START_TAG.length, endIdx).trim().toLowerCase();
|
|
1293
|
-
// Check if it's a known intent value
|
|
1294
|
-
const knownIntentValues = ['no_edit', 'low', 'medium', 'high'];
|
|
1295
|
-
if (!knownIntentValues.includes(intentValue)) {
|
|
1296
|
-
parseError = `unknownIntentValue:${intentValue}`;
|
|
1297
|
-
tracer.warn(`Unknown edit_intent value: "${intentValue}", defaulting to High`);
|
|
1298
|
-
}
|
|
1299
|
-
editIntent = xtabPromptOptions.EditIntent.fromString(intentValue);
|
|
1300
|
-
tracer.trace(`Parsed edit_intent from first line: "${intentValue}" -> ${editIntent}`);
|
|
1301
|
-
// Calculate remaining content after the end tag on the first line
|
|
1302
|
-
const afterEndTag = firstLine.substring(endIdx + EDIT_INTENT_END_TAG.length);
|
|
1303
|
-
// Create a new stream that first yields remaining content from first line, then continues
|
|
1304
|
-
const remainingLinesStream = (async function* () {
|
|
1305
|
-
// Only yield remaining content from first line if non-empty
|
|
1306
|
-
if (afterEndTag.trim() !== '') {
|
|
1307
|
-
yield afterEndTag;
|
|
1308
|
-
}
|
|
1309
|
-
// Continue with rest of the stream
|
|
1310
|
-
let next = await linesIter.next();
|
|
1311
|
-
while (!next.done) {
|
|
1312
|
-
yield next.value;
|
|
1313
|
-
next = await linesIter.next();
|
|
1314
|
-
}
|
|
1315
|
-
})();
|
|
1316
|
-
return { editIntent, remainingLinesStream, parseError };
|
|
1317
|
-
}
|
|
1318
|
-
// Determine the parse error type
|
|
1319
|
-
if (startIdx !== -1 && endIdx === -1) {
|
|
1320
|
-
// Start tag found but no end tag - malformed (possibly split across lines)
|
|
1321
|
-
parseError = 'malformedTag:startWithoutEnd';
|
|
1322
|
-
}
|
|
1323
|
-
else if (startIdx === -1 && endIdx !== -1) {
|
|
1324
|
-
// End tag found but no start tag - malformed
|
|
1325
|
-
parseError = 'malformedTag:endWithoutStart';
|
|
1326
|
-
}
|
|
1327
|
-
else {
|
|
1328
|
-
// No tag found at all
|
|
1329
|
-
parseError = 'noTagFound';
|
|
1330
|
-
}
|
|
1331
|
-
tracer.warn(`Edit intent parse error: ${parseError} (using Xtab275EditIntent prompting strategy). ` +
|
|
1332
|
-
`Defaulting to High (always show). First line was: "${firstLine.substring(0, 100)}..."`);
|
|
1333
|
-
// Return the first line plus the rest of the stream
|
|
1334
|
-
const remainingLinesStream = (async function* () {
|
|
1335
|
-
yield firstLine;
|
|
1336
|
-
let next = await linesIter.next();
|
|
1337
|
-
while (!next.done) {
|
|
1338
|
-
yield next.value;
|
|
1339
|
-
next = await linesIter.next();
|
|
1340
|
-
}
|
|
1341
|
-
})();
|
|
1342
|
-
return { editIntent, remainingLinesStream, parseError };
|
|
1343
|
-
}
|
|
1344
|
-
/**
|
|
1345
|
-
* Finds the range of lines containing merge conflict markers within a specified edit window.
|
|
1346
|
-
*
|
|
1347
|
-
* @param lines - Array of strings representing the lines of text to search through
|
|
1348
|
-
* @param editWindowRange - The range within which to search for merge conflict markers
|
|
1349
|
-
* @param maxMergeConflictLines - Maximum number of lines to search for conflict markers
|
|
1350
|
-
* @returns An OffsetRange object representing the start and end of the conflict markers, or undefined if not found
|
|
1351
|
-
*/
|
|
1352
|
-
function findMergeConflictMarkersRange(lines, editWindowRange, maxMergeConflictLines) {
|
|
1353
|
-
for (let i = editWindowRange.start; i < Math.min(lines.length, editWindowRange.endExclusive); ++i) {
|
|
1354
|
-
if (!lines[i].startsWith('<<<<<<<')) {
|
|
1355
|
-
continue;
|
|
1356
|
-
}
|
|
1357
|
-
// found start of merge conflict markers -- now find the end
|
|
1358
|
-
for (let j = i + 1; j < lines.length && (j - i) < maxMergeConflictLines; ++j) {
|
|
1359
|
-
if (lines[j].startsWith('>>>>>>>')) {
|
|
1360
|
-
return new offsetRange_1.OffsetRange(i, j + 1 /* because endExclusive */);
|
|
1361
|
-
}
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
return undefined;
|
|
1365
|
-
}
|
|
1366
1294
|
//# sourceMappingURL=xtabProvider.js.map
|