Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/inlineEdits/common/statelessNextEditProvider.ts
13400 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { Raw } from '@vscode/prompt-tsx';
7
import { Result } from '../../../util/common/result';
8
import { assert, assertNever } from '../../../util/vs/base/common/assert';
9
import { DeferredPromise } from '../../../util/vs/base/common/async';
10
import { CancellationToken, CancellationTokenSource } from '../../../util/vs/base/common/cancellation';
11
import { URI } from '../../../util/vs/base/common/uri';
12
import { LineEdit, LineReplacement, SerializedLineEdit } from '../../../util/vs/editor/common/core/edits/lineEdit';
13
import { StringEdit } from '../../../util/vs/editor/common/core/edits/stringEdit';
14
import { Position } from '../../../util/vs/editor/common/core/position';
15
import { OffsetRange } from '../../../util/vs/editor/common/core/ranges/offsetRange';
16
import { StringText } from '../../../util/vs/editor/common/core/text/abstractText';
17
import { ChatFetchResponseType, FetchResponse } from '../../chat/common/commonTypes';
18
import { ILogger } from '../../log/common/logService';
19
import { ISerializedOffsetRange, LogEntry, serializeOffsetRange } from '../../workspaceRecorder/common/workspaceLog';
20
import { DocumentId } from './dataTypes/documentId';
21
import { Edits } from './dataTypes/edit';
22
import { SerializedEdit } from './dataTypes/editUtils';
23
import { LanguageId } from './dataTypes/languageId';
24
import { DebugRecorderBookmark } from './debugRecorderBookmark';
25
import { InlineEditRequestLogContext } from './inlineEditLogContext';
26
import { stringifyChatMessages } from './utils/stringifyChatMessages';
27
import { IXtabHistoryEntry } from './workspaceEditTracker/nesXtabHistoryTracker';
28
29
export type EditStreaming = AsyncGenerator<StreamedEdit, NoNextEditReason, void>;
30
31
export class WithStatelessProviderTelemetry<T> {
32
constructor(
33
public readonly v: T,
34
public readonly telemetryBuilder: IStatelessNextEditTelemetry,
35
) {
36
}
37
}
38
39
export type EditStreamingWithTelemetry = AsyncGenerator<WithStatelessProviderTelemetry<StreamedEdit>, WithStatelessProviderTelemetry<NoNextEditReason>, void>;
40
41
export type StreamedEdit = {
42
readonly targetDocument: DocumentId;
43
readonly edit: LineReplacement;
44
readonly isFromCursorJump: boolean;
45
readonly window?: OffsetRange;
46
/**
47
* For cursor jump edits, this is the edit window around the original cursor position
48
* (before the jump). This allows the cached edit to be served when the cursor is
49
* in either the original location or the jump target location.
50
*/
51
readonly originalWindow?: OffsetRange;
52
};
53
54
export type PushEdit = (edit: Result<StreamedEdit, NoNextEditReason>) => void;
55
56
export class RequestEditWindow {
57
constructor(readonly window: OffsetRange) { }
58
containsCursor(cursor: OffsetRange): boolean {
59
return this.window.containsRange(cursor);
60
}
61
}
62
63
export class RequestEditWindowWithCursorJump {
64
constructor(readonly window: OffsetRange, readonly originalWindow: OffsetRange) { }
65
containsCursor(cursor: OffsetRange): boolean {
66
return this.window.containsRange(cursor) || this.originalWindow.containsRange(cursor);
67
}
68
}
69
70
export interface IStatelessNextEditProvider {
71
readonly ID: string;
72
provideNextEdit(request: StatelessNextEditRequest, logger: ILogger, logContext: InlineEditRequestLogContext, cancellationToken: CancellationToken): EditStreamingWithTelemetry;
73
handleAcceptance?(): void;
74
handleRejection?(): void;
75
handleIgnored?(): void;
76
}
77
78
export class StatelessNextEditRequest<TFirstEdit = any> {
79
80
private static ID = 0;
81
public readonly seqid = String(++StatelessNextEditRequest.ID);
82
83
public readonly cancellationTokenSource = new CancellationTokenSource();
84
public liveDependentants = 0; // number of invocations which haven't been canceled and depend on this request
85
public fetchIssued = false;
86
public intermediateUserEdit: StringEdit | undefined = StringEdit.empty;
87
88
/**
89
* Set by the stateless provider early in its execution (before any async work).
90
* Used to check whether a new cursor position falls within the edit window when
91
* deciding whether to reuse an in-flight request.
92
*/
93
public requestEditWindow: RequestEditWindow | RequestEditWindowWithCursorJump | undefined;
94
95
private readonly _result: DeferredPromise<StatelessNextEditResult> = new DeferredPromise<StatelessNextEditResult>();
96
public get result(): Promise<StatelessNextEditResult> {
97
return this._result.p;
98
}
99
100
constructor(
101
public readonly headerRequestId: string,
102
public readonly opportunityId: string,
103
/** this's the active document current contents (not sure "before" which edits this's named after -- maybe NES edits) */
104
public readonly documentBeforeEdits: StringText,
105
public readonly documents: readonly StatelessNextEditDocument[],
106
public readonly activeDocumentIdx: number,
107
public readonly xtabEditHistory: readonly IXtabHistoryEntry[],
108
public readonly firstEdit: DeferredPromise<Result<TFirstEdit, NoNextEditReason>>,
109
public readonly expandedEditWindowNLines: number | undefined,
110
public readonly isSpeculative: boolean,
111
public readonly logContext: InlineEditRequestLogContext,
112
public readonly recordingBookmark: DebugRecorderBookmark | undefined,
113
public readonly recording: LogEntry[] | undefined,
114
public readonly providerRequestStartDateTime: number | undefined,
115
) {
116
assert(documents.length > 0);
117
assert(activeDocumentIdx >= 0 && activeDocumentIdx < documents.length);
118
}
119
120
public setResult(nextEditResult: StatelessNextEditResult) {
121
this._result.complete(nextEditResult);
122
}
123
124
public setResultError(err: any) {
125
this._result.error(err);
126
}
127
128
public hasDocument(docId: DocumentId): boolean {
129
return this.documents.find(d => d.id === docId) !== undefined;
130
}
131
132
getActiveDocument(): StatelessNextEditDocument {
133
return this.documents[this.activeDocumentIdx];
134
}
135
136
serialize(): ISerializedNextEditRequest {
137
return {
138
id: this.headerRequestId,
139
documents: this.documents.map(d => d.serialize()),
140
activeDocumentIdx: this.activeDocumentIdx,
141
recording: this.recording,
142
};
143
}
144
145
toString(): string {
146
return this.toMarkdown();
147
}
148
149
toMarkdown(): string {
150
const docs = this.documents.map((d, idx) => ` * [${idx + 1}/${this.documents.length}] ${idx === this.activeDocumentIdx ? '(active document) ' : ''}` + d.toMarkdown()).join('\n\n');
151
return `### StatelessNextEditRequest\n\n${docs}`;
152
}
153
}
154
155
export interface ISerializedNextEditRequest {
156
id: string;
157
documents: ISerializedNextEditDocument[];
158
activeDocumentIdx: number;
159
recording: LogEntry[] | undefined;
160
}
161
162
export class StatelessNextEditDocument {
163
public readonly documentAfterEdits = new StringText(this.recentEdits.apply(this.documentBeforeEdits.value));
164
public readonly documentAfterEditsLines: string[] = this.documentAfterEdits.getLines();
165
166
/**
167
* NOTE: if you add new public fields to this class, please also update {@link ISerializedNextEditDocument} and {@link serialize()} methods,
168
* which are used to send this to http-server-powered NES provider.
169
*/
170
constructor(
171
public readonly id: DocumentId,
172
public readonly workspaceRoot: URI | undefined,
173
public readonly languageId: LanguageId,
174
public readonly documentLinesBeforeEdit: string[],
175
public readonly recentEdit: LineEdit,
176
public readonly documentBeforeEdits: StringText,
177
public readonly recentEdits: Edits,
178
public readonly lastSelectionInAfterEdit: OffsetRange | undefined = undefined,
179
) { }
180
181
serialize(): ISerializedNextEditDocument {
182
return {
183
id: this.id.uri,
184
workspaceRoot: this.workspaceRoot?.toString(),
185
languageId: this.languageId,
186
documentLinesBeforeEdit: this.documentLinesBeforeEdit,
187
recentEdit: this.recentEdit.serialize(),
188
documentBeforeEdits: this.documentBeforeEdits.value,
189
recentEdits: this.recentEdits.serialize(),
190
lastSelectionInAfterEdit: this.lastSelectionInAfterEdit === undefined ? undefined : serializeOffsetRange(this.lastSelectionInAfterEdit),
191
};
192
}
193
194
toString(): string {
195
return this.toMarkdown();
196
}
197
198
toMarkdown(): string {
199
const lines: string[] = [];
200
201
lines.push(`StatelessNextEditDocument: **${this.id.uri}**\n`);
202
lines.push('```patch');
203
lines.push(this.recentEdit.humanReadablePatch(this.documentLinesBeforeEdit));
204
lines.push('```');
205
lines.push('');
206
207
return lines.join('\n');
208
}
209
}
210
211
export interface ISerializedNextEditDocument {
212
id: string;
213
workspaceRoot: string | undefined;
214
languageId: string;
215
documentLinesBeforeEdit: string[];
216
recentEdit: SerializedLineEdit;
217
documentBeforeEdits: string;
218
recentEdits: SerializedEdit[];
219
lastSelectionInAfterEdit: ISerializedOffsetRange | undefined;
220
}
221
222
export enum FilteredOutReason {
223
LowLogProbSuggestions = 'lowLogProbSuggestions',
224
EnforcingNextEditOptions = 'enforcingNextEditOptions',
225
PromptTooLarge = 'promptTooLarge',
226
Uncategorized = 'uncategorized',
227
}
228
229
export namespace NoNextEditReason {
230
abstract class NoNextEditReason {
231
abstract toString(): string;
232
}
233
export class ActiveDocumentHasNoEdits extends NoNextEditReason {
234
public readonly kind = 'activeDocumentHasNoEdits';
235
236
toString(): string {
237
return this.kind;
238
}
239
}
240
export class NoSuggestions extends NoNextEditReason {
241
public readonly kind = 'noSuggestions';
242
243
constructor(
244
public readonly documentBeforeEdits: StringText,
245
public readonly window: OffsetRange | undefined,
246
public readonly nextCursorPosition?: Position | undefined,
247
public readonly nextCursorDocumentId?: DocumentId | undefined,
248
) {
249
super();
250
}
251
252
toString(): string {
253
return this.kind;
254
}
255
}
256
export class GotCancelled extends NoNextEditReason {
257
public readonly kind = 'gotCancelled';
258
constructor(public readonly message: string | 'afterDebounce' | 'afterGettingEndpoint' | 'afterLanguageContextAwait' | 'afterPromptConstruction' | 'afterFetchCall' | 'duringStreaming' | 'afterResponse' | 'afterFailedRebase' | 'beforeExecutingNewRequest' | 'afterArtificialDelay' | 'afterNextCursorPredictionFetch') {
259
super();
260
}
261
262
toString(): string {
263
return `${this.kind}:${this.message}`;
264
}
265
}
266
export class FetchFailure extends NoNextEditReason {
267
public readonly kind = 'fetchFailure';
268
constructor(public readonly error: Error) {
269
super();
270
}
271
toString(): string {
272
return `${this.kind}:${this.error.message}`;
273
}
274
}
275
export class FilteredOut extends NoNextEditReason {
276
public readonly kind = 'filteredOut';
277
constructor(public readonly message: FilteredOutReason | string) {
278
super();
279
}
280
toString(): string {
281
return `${this.kind}:${this.message}`;
282
}
283
}
284
export class PromptTooLarge extends NoNextEditReason {
285
public readonly kind = 'promptTooLarge';
286
constructor(public readonly message: 'editWindow' | 'currentFile' | 'final') {
287
super();
288
}
289
toString(): string {
290
return `${this.kind}:${this.message}`;
291
}
292
}
293
export class Uncategorized extends NoNextEditReason {
294
public readonly kind = 'uncategorized';
295
constructor(public readonly error: Error) {
296
super();
297
}
298
toString(): string {
299
return `${this.kind}:${this.error.message}`;
300
}
301
}
302
export class Unexpected extends NoNextEditReason {
303
public readonly kind = 'unexpected';
304
constructor(public readonly error: Error) {
305
super();
306
}
307
toString(): string {
308
return `${this.kind}:${this.error.message}`;
309
}
310
}
311
}
312
313
export type NoNextEditReason =
314
| NoNextEditReason.ActiveDocumentHasNoEdits
315
| NoNextEditReason.NoSuggestions
316
| NoNextEditReason.GotCancelled
317
| NoNextEditReason.FetchFailure
318
| NoNextEditReason.FilteredOut
319
| NoNextEditReason.PromptTooLarge
320
| NoNextEditReason.Uncategorized
321
| NoNextEditReason.Unexpected
322
;
323
324
export class StatelessNextEditResult {
325
public static noEdit(reason: NoNextEditReason, telemetryBuilder: StatelessNextEditTelemetryBuilder): StatelessNextEditResult {
326
const result = Result.error(reason);
327
const telemetry = telemetryBuilder.build(result);
328
return new StatelessNextEditResult(result, telemetry);
329
}
330
331
public static streaming(telemetryBuilder: StatelessNextEditTelemetryBuilder): StatelessNextEditResult {
332
const result = Result.ok<void>(undefined);
333
const telemetry = telemetryBuilder.build(result);
334
return new StatelessNextEditResult(result, telemetry);
335
}
336
337
constructor(
338
public readonly nextEdit: Result<void, NoNextEditReason>,
339
public readonly telemetry: IStatelessNextEditTelemetry,
340
) {
341
}
342
}
343
344
export interface IStatelessNextEditTelemetry {
345
346
readonly hadStatelessNextEditProviderCall: boolean;
347
348
/* general info */
349
readonly statelessNextEditProviderDuration: number;
350
readonly isCursorAtEndOfLine: boolean | undefined;
351
readonly isInlineSuggestion: boolean | undefined;
352
readonly nLinesOfCurrentFileInPrompt: number | undefined;
353
readonly modelName: string | undefined;
354
355
/* options info */
356
readonly logProbThreshold: number | undefined;
357
358
/* prompt info */
359
360
readonly prompt: string | undefined;
361
readonly promptLineCount: number | undefined;
362
readonly promptCharCount: number | undefined;
363
readonly mergeConflictExpanded: 'normal' | 'only' | undefined;
364
365
/* fetch request info */
366
367
readonly debounceTime: number | undefined;
368
/** This's only used to compute time from inline edit provider call to fetch init. Not included in telemetry. */
369
readonly fetchStartedAt: number | undefined;
370
371
/* response info */
372
373
/** Artificial delay (aka backoff) on the response based on previous user acceptance/rejection in milliseconds */
374
readonly artificialDelay: number | undefined;
375
376
readonly hadLowLogProbSuggestion: boolean | undefined;
377
readonly response: undefined | Promise<FetchResultWithStats>;
378
379
/* suggestions info */
380
381
readonly nEditsSuggested: number | undefined;
382
readonly lineDistanceToMostRecentEdit: number | undefined;
383
384
/* result info */
385
readonly nextEditLogprob: number | undefined;
386
readonly noNextEditReasonKind: string | undefined;
387
readonly noNextEditReasonMessage: string | undefined;
388
389
/* next cursor line info */
390
readonly nextCursorPrediction: {
391
nextCursorLineError: string | undefined;
392
/** nextCursorLineNumber - currentCursorLineNumber */
393
nextCursorLineDistance: number | undefined;
394
isCrossFile: boolean | undefined;
395
};
396
397
/* xtab aggressiveness telemetry (only set when promptingStrategy is aggressiveness-based) */
398
readonly xtabAggressivenessLevel: string | undefined;
399
readonly xtabUserHappinessScore: number | undefined;
400
401
/** The raw user-facing aggressiveness setting value (only set when user changed from default) */
402
readonly userAggressivenessSetting: string | undefined;
403
404
/* edit intent telemetry (only set when promptingStrategy is Xtab275EditIntent or Xtab275EditIntentShort) */
405
readonly editIntent: string | undefined;
406
readonly editIntentParseError: string | undefined;
407
408
/* cursor jump info */
409
readonly cursorJumpModelName: string | undefined;
410
readonly cursorJumpPrompt: string | undefined;
411
readonly cursorJumpResponse: string | undefined;
412
413
/* diff history info */
414
readonly nDiffsInPrompt: number | undefined;
415
readonly diffTokensInPrompt: number | undefined;
416
417
/* neighbor (similar files) snippets info */
418
readonly nNeighborSnippetsComputed: number | undefined;
419
readonly nNeighborSnippetsInPrompt: number | undefined;
420
/** JSON-encoded array of original input indices of snippets included in the prompt. */
421
readonly neighborSnippetIndicesInPrompt: string | undefined;
422
423
/* lint errors info */
424
readonly lintErrors: string | undefined;
425
426
/* terminal output info */
427
readonly terminalOutput: string | undefined;
428
429
/* similar files context for telemetry (GhostText-style neighbor code snippets) */
430
readonly similarFilesContext: Promise<string | undefined> | undefined;
431
432
/* JSON-encoded model configuration from the model service */
433
readonly modelConfig: string | undefined;
434
}
435
436
export type FetchResultWithStats = {
437
readonly ttft: number | undefined;
438
readonly response: FetchResponse<string>;
439
readonly fetchTime: number;
440
readonly fetchResult: ChatFetchResponseType;
441
};
442
443
export class StatelessNextEditTelemetryBuilder {
444
445
public readonly startTime: number;
446
public readonly requestUuid: string;
447
448
/**
449
* It takes a request to automatically capture some properties from the request.
450
*/
451
constructor(headerRequestId: string) {
452
this.startTime = Date.now();
453
this.requestUuid = headerRequestId;
454
}
455
456
public build(result: Result<void, NoNextEditReason>): IStatelessNextEditTelemetry {
457
const endTime = Date.now();
458
const timeSpent = endTime - this.startTime;
459
460
const prompt = this._prompt ? JSON.stringify(this._prompt.map(({ role, content }) => ({ role, content }))) : undefined;
461
const promptText = this._prompt ? stringifyChatMessages(this._prompt) : undefined;
462
const promptLineCount = promptText?.split('\n').length;
463
const promptCharCount = promptText?.length;
464
465
const noNextEditReasonKind = result.isOk() ? undefined : result.err.kind;
466
467
let noNextEditReasonMessage: string | undefined;
468
if (result.isError()) {
469
if (result.err instanceof NoNextEditReason.ActiveDocumentHasNoEdits || result.err instanceof NoNextEditReason.NoSuggestions) {
470
// ignore
471
} else if (result.err instanceof NoNextEditReason.GotCancelled || result.err instanceof NoNextEditReason.FilteredOut || result.err instanceof NoNextEditReason.PromptTooLarge) {
472
noNextEditReasonMessage = result.err.message;
473
} else if (result.err instanceof NoNextEditReason.FetchFailure || result.err instanceof NoNextEditReason.Uncategorized || result.err instanceof NoNextEditReason.Unexpected) {
474
noNextEditReasonMessage = result.err.error.stack ? result.err.error.stack : result.err.error.message;
475
} else {
476
assertNever(result.err);
477
}
478
}
479
480
return {
481
hadStatelessNextEditProviderCall: true,
482
483
noNextEditReasonKind,
484
noNextEditReasonMessage,
485
486
statelessNextEditProviderDuration: timeSpent,
487
logProbThreshold: this._logProbThreshold,
488
mergeConflictExpanded: this._mergeConflictExpanded,
489
nLinesOfCurrentFileInPrompt: this._nLinesOfCurrentFileInPrompt,
490
modelName: this._modelName,
491
prompt,
492
promptLineCount,
493
promptCharCount,
494
isCursorAtEndOfLine: this._isCursorAtLineEnd,
495
isInlineSuggestion: this._isInlineSuggestion,
496
debounceTime: this._debounceTime,
497
artificialDelay: this._artificialDelay,
498
fetchStartedAt: this._fetchStartedAt,
499
hadLowLogProbSuggestion: this._hadLowLogProbSuggestion,
500
response: this._response,
501
nEditsSuggested: this._nEditsSuggested,
502
nextEditLogprob: this._nextEditLogProb,
503
nextCursorPrediction: this._nextCursorPrediction,
504
lineDistanceToMostRecentEdit: this._lineDistanceToMostRecentEdit,
505
xtabAggressivenessLevel: this._xtabAggressivenessLevel,
506
xtabUserHappinessScore: this._xtabUserHappinessScore,
507
userAggressivenessSetting: this._userAggressivenessSetting,
508
editIntent: this._editIntent,
509
editIntentParseError: this._editIntentParseError,
510
cursorJumpModelName: this._cursorJumpModelName,
511
cursorJumpPrompt: this._cursorJumpPrompt ? JSON.stringify(this._cursorJumpPrompt.map(({ role, content }) => ({ role, content }))) : undefined,
512
cursorJumpResponse: this._cursorJumpResponse,
513
nDiffsInPrompt: this._nDiffsInPrompt,
514
diffTokensInPrompt: this._diffTokensInPrompt,
515
nNeighborSnippetsComputed: this._nNeighborSnippetsComputed,
516
nNeighborSnippetsInPrompt: this._nNeighborSnippetsInPrompt,
517
neighborSnippetIndicesInPrompt: this._neighborSnippetIndicesInPrompt,
518
lintErrors: this._lintErrors,
519
terminalOutput: this._terminalOutput,
520
similarFilesContext: this._similarFilesContext,
521
modelConfig: this._modelConfig,
522
};
523
}
524
525
private _logProbThreshold: number | undefined;
526
public setLogProbThreshold(logProbThreshold: number): this {
527
this._logProbThreshold = logProbThreshold;
528
return this;
529
}
530
531
private _mergeConflictExpanded: 'normal' | 'only' | undefined;
532
public setMergeConflictExpanded(mergeConflictExpanded: 'normal' | 'only'): this {
533
this._mergeConflictExpanded = mergeConflictExpanded;
534
return this;
535
}
536
537
private _hadLowLogProbSuggestion: boolean | undefined;
538
public setHadLowLogProbSuggestion(hadLowLogProbSuggestions: boolean): this {
539
this._hadLowLogProbSuggestion = hadLowLogProbSuggestions;
540
return this;
541
}
542
543
private _nLinesOfCurrentFileInPrompt: number | undefined;
544
public setNLinesOfCurrentFileInPrompt(nLines: number): this {
545
this._nLinesOfCurrentFileInPrompt = nLines;
546
return this;
547
}
548
549
private _modelName: string | undefined;
550
public setModelName(modelName: string): this {
551
this._modelName = modelName;
552
return this;
553
}
554
555
private _prompt: Raw.ChatMessage[] | undefined;
556
public setPrompt(prompt: Raw.ChatMessage[]): this {
557
this._prompt = prompt;
558
return this;
559
}
560
561
private _isCursorAtLineEnd: boolean | undefined;
562
public setIsCursorAtLineEnd(isCursorAtLineEnd: boolean): this {
563
this._isCursorAtLineEnd = isCursorAtLineEnd;
564
return this;
565
}
566
567
private _isInlineSuggestion: boolean | undefined;
568
public setIsInlineSuggestion(isInlineSuggestion: boolean): this {
569
this._isInlineSuggestion = isInlineSuggestion;
570
return this;
571
}
572
573
private _debounceTime: number | undefined;
574
public setDebounceTime(debounceTime: number): this {
575
this._debounceTime = debounceTime;
576
return this;
577
}
578
579
private _artificialDelay: number | undefined;
580
public setArtificialDelay(artificialDelay: number): this {
581
this._artificialDelay = artificialDelay;
582
return this;
583
}
584
585
private _fetchStartedAt: number | undefined;
586
public setFetchStartedAt(): this {
587
this._fetchStartedAt = Date.now();
588
return this;
589
}
590
public get fetchStartedAt(): number | undefined {
591
return this._fetchStartedAt;
592
}
593
594
private _response: Promise<FetchResultWithStats> | undefined;
595
public setResponse(response: Promise<{ ttft: number | undefined; response: FetchResponse<string> }>): this {
596
this._response = response.then(({ response, ttft }) => {
597
598
const fetchTime = Date.now() - this._fetchStartedAt!;
599
600
const fetchResult = response.type;
601
602
return {
603
ttft,
604
response,
605
fetchTime,
606
fetchResult,
607
};
608
});
609
610
return this;
611
}
612
613
private _cursorJumpModelName: string | undefined;
614
public setCursorJumpModelName(modelName: string | undefined): this {
615
this._cursorJumpModelName = modelName;
616
return this;
617
}
618
619
private _cursorJumpPrompt: Raw.ChatMessage[] | undefined;
620
public setCursorJumpPrompt(prompt: Raw.ChatMessage[] | undefined): this {
621
this._cursorJumpPrompt = prompt;
622
return this;
623
}
624
625
private _cursorJumpResponse: string | undefined;
626
public setCursorJumpResponse(response: string | undefined): this {
627
this._cursorJumpResponse = response;
628
return this;
629
}
630
631
private _nextEditLogProb: number | undefined;
632
public setNextEditLogProb(logProb: number): this {
633
this._nextEditLogProb = logProb;
634
return this;
635
}
636
637
private _nEditsSuggested: number | undefined;
638
public setNEditsSuggested(nEditsSuggested: number): this {
639
this._nEditsSuggested = nEditsSuggested;
640
return this;
641
}
642
643
private _lineDistanceToMostRecentEdit: number | undefined;
644
public setLineDistanceToMostRecentEdit(distanceToMostRecentEdit: number): this {
645
this._lineDistanceToMostRecentEdit = distanceToMostRecentEdit;
646
return this;
647
}
648
649
private _nextCursorPrediction: IStatelessNextEditTelemetry['nextCursorPrediction'] = {
650
nextCursorLineError: undefined,
651
nextCursorLineDistance: undefined,
652
isCrossFile: undefined
653
};
654
655
public setNextCursorLineError(error: string): this {
656
this._nextCursorPrediction.nextCursorLineError = error;
657
return this;
658
}
659
660
/**
661
* nextCursorLineNumber - currentCursorLineNumber
662
*/
663
public setNextCursorLineDistance(distance: number): this {
664
this._nextCursorPrediction.nextCursorLineDistance = distance;
665
return this;
666
}
667
668
public setNextCursorIsCrossFile(isCrossFile: boolean): this {
669
this._nextCursorPrediction.isCrossFile = isCrossFile;
670
return this;
671
}
672
673
private _xtabAggressivenessLevel: string | undefined;
674
public setXtabAggressivenessLevel(level: string): this {
675
this._xtabAggressivenessLevel = level;
676
return this;
677
}
678
679
private _xtabUserHappinessScore: number | undefined;
680
public setXtabUserHappinessScore(score: number): this {
681
this._xtabUserHappinessScore = score;
682
return this;
683
}
684
685
private _userAggressivenessSetting: string | undefined;
686
public setUserAggressivenessSetting(setting: string): this {
687
this._userAggressivenessSetting = setting;
688
return this;
689
}
690
691
private _editIntent: string | undefined;
692
public setEditIntent(editIntent: string): this {
693
this._editIntent = editIntent;
694
return this;
695
}
696
697
private _editIntentParseError: string | undefined;
698
public setEditIntentParseError(error: string): this {
699
this._editIntentParseError = error;
700
return this;
701
}
702
703
private _nDiffsInPrompt: number | undefined;
704
public setNDiffsInPrompt(n: number): this {
705
this._nDiffsInPrompt = n;
706
return this;
707
}
708
709
private _diffTokensInPrompt: number | undefined;
710
public setDiffTokensInPrompt(n: number): this {
711
this._diffTokensInPrompt = n;
712
return this;
713
}
714
715
private _nNeighborSnippetsComputed: number | undefined;
716
public setNNeighborSnippetsComputed(n: number): this {
717
this._nNeighborSnippetsComputed = n;
718
return this;
719
}
720
721
private _nNeighborSnippetsInPrompt: number | undefined;
722
public setNNeighborSnippetsInPrompt(n: number): this {
723
this._nNeighborSnippetsInPrompt = n;
724
return this;
725
}
726
727
private _neighborSnippetIndicesInPrompt: string | undefined;
728
public setNeighborSnippetIndicesInPrompt(indices: readonly number[]): this {
729
this._neighborSnippetIndicesInPrompt = JSON.stringify(indices);
730
return this;
731
}
732
733
private _lintErrors: string | undefined;
734
public setLintErrors(lintErrors: string): this {
735
this._lintErrors = lintErrors;
736
return this;
737
}
738
739
private _terminalOutput: string | undefined;
740
public setTerminalOutput(terminalOutput: string): this {
741
this._terminalOutput = terminalOutput;
742
return this;
743
}
744
745
private _similarFilesContext: Promise<string | undefined> | undefined;
746
public setSimilarFilesContext(similarFilesContext: Promise<string | undefined>): this {
747
this._similarFilesContext = similarFilesContext;
748
return this;
749
}
750
751
private _modelConfig: string | undefined;
752
public setModelConfig(modelConfig: string): this {
753
this._modelConfig = modelConfig;
754
return this;
755
}
756
}
757
758