import { Raw } from '@vscode/prompt-tsx'; import { Result } from '../../../util/common/result'; import { DeferredPromise } from '../../../util/vs/base/common/async'; import { CancellationToken, CancellationTokenSource } from '../../../util/vs/base/common/cancellation'; import { URI } from '../../../util/vs/base/common/uri'; import { LineEdit, LineReplacement, SerializedLineEdit } from '../../../util/vs/editor/common/core/edits/lineEdit'; import { StringEdit } from '../../../util/vs/editor/common/core/edits/stringEdit'; import { Position } from '../../../util/vs/editor/common/core/position'; import { OffsetRange } from '../../../util/vs/editor/common/core/ranges/offsetRange'; import { StringText } from '../../../util/vs/editor/common/core/text/abstractText'; import { ChatFetchResponseType, FetchResponse } from '../../chat/common/commonTypes'; import { ILogger } from '../../log/common/logService'; import { ISerializedOffsetRange, LogEntry } from '../../workspaceRecorder/common/workspaceLog'; import { DocumentId } from './dataTypes/documentId'; import { Edits } from './dataTypes/edit'; import { SerializedEdit } from './dataTypes/editUtils'; import { LanguageId } from './dataTypes/languageId'; import { PromptSectionTokenCounts } from './dataTypes/promptSectionTokens'; import { DebugRecorderBookmark } from './debugRecorderBookmark'; import { InlineEditRequestLogContext } from './inlineEditLogContext'; import { IXtabHistoryEntry, IXtabHistoryRejectedEditEntry } from './workspaceEditTracker/nesXtabHistoryTracker'; export type EditStreaming = AsyncGenerator; export declare class WithStatelessProviderTelemetry { readonly v: T; readonly telemetryBuilder: IStatelessNextEditTelemetry; constructor(v: T, telemetryBuilder: IStatelessNextEditTelemetry); } export type EditStreamingWithTelemetry = AsyncGenerator, WithStatelessProviderTelemetry, void>; export type StreamedEdit = { readonly targetDocument: DocumentId; readonly edit: LineReplacement; readonly isFromCursorJump: boolean; readonly window?: OffsetRange; /** * For cursor jump edits, this is the edit window around the original cursor position * (before the jump). This allows the cached edit to be served when the cursor is * in either the original location or the jump target location. */ readonly originalWindow?: OffsetRange; /** * Zero-based index of the model-emitted patch this edit originated from, for the * diff-patch response format. A single model patch can expand into several edits * (per-patch diff splitting or progressive ghost-text reveal); all edits produced * from the same patch share the same `patchIndex`. `undefined` for response formats * that have no explicit patch structure (e.g. edit-window, INSERT). */ readonly patchIndex?: number; }; export type PushEdit = (edit: Result) => void; export declare class RequestEditWindow { readonly window: OffsetRange; constructor(window: OffsetRange); containsCursor(cursor: OffsetRange): boolean; } export declare class RequestEditWindowWithCursorJump { readonly window: OffsetRange; readonly originalWindow: OffsetRange; constructor(window: OffsetRange, originalWindow: OffsetRange); containsCursor(cursor: OffsetRange): boolean; } export interface IStatelessNextEditProvider { readonly ID: string; provideNextEdit(request: StatelessNextEditRequest, logger: ILogger, logContext: InlineEditRequestLogContext, cancellationToken: CancellationToken): EditStreamingWithTelemetry; handleAcceptance?(): void; handleRejection?(): void; handleIgnored?(): void; } export declare class StatelessNextEditRequest { readonly headerRequestId: string; readonly opportunityId: string; /** this's the active document current contents (not sure "before" which edits this's named after -- maybe NES edits) */ readonly documentBeforeEdits: StringText; readonly documents: readonly StatelessNextEditDocument[]; readonly activeDocumentIdx: number; readonly xtabEditHistory: readonly IXtabHistoryEntry[]; readonly firstEdit: DeferredPromise>; readonly expandedEditWindowNLines: number | undefined; readonly isSpeculative: boolean; readonly logContext: InlineEditRequestLogContext; readonly recordingBookmark: DebugRecorderBookmark | undefined; readonly recording: LogEntry[] | undefined; readonly providerRequestStartDateTime: number | undefined; readonly xtabRejectedEditHistory: readonly IXtabHistoryRejectedEditEntry[]; private static ID; readonly seqid: string; readonly cancellationTokenSource: CancellationTokenSource; liveDependentants: number; fetchIssued: boolean; intermediateUserEdit: StringEdit | undefined; /** * Set by the stateless provider early in its execution (before any async work). * Used to check whether a new cursor position falls within the edit window when * deciding whether to reuse an in-flight request. */ requestEditWindow: RequestEditWindow | RequestEditWindowWithCursorJump | undefined; private readonly _result; get result(): Promise; constructor(headerRequestId: string, opportunityId: string, /** this's the active document current contents (not sure "before" which edits this's named after -- maybe NES edits) */ documentBeforeEdits: StringText, documents: readonly StatelessNextEditDocument[], activeDocumentIdx: number, xtabEditHistory: readonly IXtabHistoryEntry[], firstEdit: DeferredPromise>, expandedEditWindowNLines: number | undefined, isSpeculative: boolean, logContext: InlineEditRequestLogContext, recordingBookmark: DebugRecorderBookmark | undefined, recording: LogEntry[] | undefined, providerRequestStartDateTime: number | undefined, xtabRejectedEditHistory: readonly IXtabHistoryRejectedEditEntry[]); setResult(nextEditResult: StatelessNextEditResult): void; setResultError(err: any): void; hasDocument(docId: DocumentId): boolean; getActiveDocument(): StatelessNextEditDocument; serialize(): ISerializedNextEditRequest; toString(): string; toMarkdown(): string; } export interface ISerializedNextEditRequest { id: string; documents: ISerializedNextEditDocument[]; activeDocumentIdx: number; recording: LogEntry[] | undefined; } export declare class StatelessNextEditDocument { readonly id: DocumentId; readonly workspaceRoot: URI | undefined; readonly languageId: LanguageId; readonly documentLinesBeforeEdit: string[]; readonly recentEdit: LineEdit; readonly documentBeforeEdits: StringText; readonly recentEdits: Edits; readonly lastSelectionInAfterEdit: OffsetRange | undefined; readonly documentAfterEdits: StringText; readonly documentAfterEditsLines: string[]; /** * NOTE: if you add new public fields to this class, please also update {@link ISerializedNextEditDocument} and {@link serialize()} methods, * which are used to send this to http-server-powered NES provider. */ constructor(id: DocumentId, workspaceRoot: URI | undefined, languageId: LanguageId, documentLinesBeforeEdit: string[], recentEdit: LineEdit, documentBeforeEdits: StringText, recentEdits: Edits, lastSelectionInAfterEdit?: OffsetRange | undefined); serialize(): ISerializedNextEditDocument; toString(): string; toMarkdown(): string; } export interface ISerializedNextEditDocument { id: string; workspaceRoot: string | undefined; languageId: string; documentLinesBeforeEdit: string[]; recentEdit: SerializedLineEdit; documentBeforeEdits: string; recentEdits: SerializedEdit[]; lastSelectionInAfterEdit: ISerializedOffsetRange | undefined; } export declare enum FilteredOutReason { LowLogProbSuggestions = "lowLogProbSuggestions", EnforcingNextEditOptions = "enforcingNextEditOptions", PromptTooLarge = "promptTooLarge", Uncategorized = "uncategorized" } export declare namespace NoNextEditReason { abstract class NoNextEditReason { abstract toString(): string; } export class ActiveDocumentHasNoEdits extends NoNextEditReason { readonly kind = "activeDocumentHasNoEdits"; toString(): string; } export class NoSuggestions extends NoNextEditReason { readonly documentBeforeEdits: StringText; readonly window: OffsetRange | undefined; readonly nextCursorPosition?: Position | undefined; readonly nextCursorDocumentId?: DocumentId | undefined; readonly kind = "noSuggestions"; constructor(documentBeforeEdits: StringText, window: OffsetRange | undefined, nextCursorPosition?: Position | undefined, nextCursorDocumentId?: DocumentId | undefined); toString(): string; } export class GotCancelled extends NoNextEditReason { readonly message: string | 'afterDebounce' | 'afterGettingEndpoint' | 'afterLanguageContextAwait' | 'afterPromptConstruction' | 'afterFetchCall' | 'duringStreaming' | 'afterResponse' | 'afterFailedRebase' | 'beforeExecutingNewRequest' | 'afterArtificialDelay' | 'afterNextCursorPredictionFetch'; readonly kind = "gotCancelled"; constructor(message: string | 'afterDebounce' | 'afterGettingEndpoint' | 'afterLanguageContextAwait' | 'afterPromptConstruction' | 'afterFetchCall' | 'duringStreaming' | 'afterResponse' | 'afterFailedRebase' | 'beforeExecutingNewRequest' | 'afterArtificialDelay' | 'afterNextCursorPredictionFetch'); toString(): string; } export class FetchFailure extends NoNextEditReason { readonly error: Error; readonly kind = "fetchFailure"; constructor(error: Error); toString(): string; } export class FilteredOut extends NoNextEditReason { readonly message: FilteredOutReason | string; readonly kind = "filteredOut"; constructor(message: FilteredOutReason | string); toString(): string; } export class PromptTooLarge extends NoNextEditReason { readonly message: 'editWindow' | 'currentFile' | 'final'; readonly kind = "promptTooLarge"; constructor(message: 'editWindow' | 'currentFile' | 'final'); toString(): string; } export class Uncategorized extends NoNextEditReason { readonly error: Error; readonly kind = "uncategorized"; constructor(error: Error); toString(): string; } export class Unexpected extends NoNextEditReason { readonly error: Error; readonly kind = "unexpected"; constructor(error: Error); toString(): string; } export {}; } export type NoNextEditReason = NoNextEditReason.ActiveDocumentHasNoEdits | NoNextEditReason.NoSuggestions | NoNextEditReason.GotCancelled | NoNextEditReason.FetchFailure | NoNextEditReason.FilteredOut | NoNextEditReason.PromptTooLarge | NoNextEditReason.Uncategorized | NoNextEditReason.Unexpected; export declare class StatelessNextEditResult { readonly nextEdit: Result; readonly telemetry: IStatelessNextEditTelemetry; static noEdit(reason: NoNextEditReason, telemetryBuilder: StatelessNextEditTelemetryBuilder): StatelessNextEditResult; static streaming(telemetryBuilder: StatelessNextEditTelemetryBuilder): StatelessNextEditResult; constructor(nextEdit: Result, telemetry: IStatelessNextEditTelemetry); } export interface IStatelessNextEditModelTelemetry { /** Name of the model that handled the request. */ readonly modelName: string | undefined; /** JSON-encoded model configuration from the model service. */ readonly modelConfig: string | undefined; } export interface IStatelessNextEditTelemetry extends IStatelessNextEditModelTelemetry { readonly hadStatelessNextEditProviderCall: boolean; readonly statelessNextEditProviderDuration: number; readonly isCursorAtEndOfLine: boolean | undefined; readonly isInlineSuggestion: boolean | undefined; readonly nLinesOfCurrentFileInPrompt: number | undefined; readonly logProbThreshold: number | undefined; readonly prompt: string | undefined; readonly promptLineCount: number | undefined; readonly promptCharCount: number | undefined; readonly mergeConflictExpanded: 'normal' | 'only' | undefined; readonly debounceTime: number | undefined; /** This's only used to compute time from inline edit provider call to fetch init. Not included in telemetry. */ readonly fetchStartedAt: number | undefined; /** Artificial delay (aka backoff) on the response based on previous user acceptance/rejection in milliseconds */ readonly artificialDelay: number | undefined; readonly hadLowLogProbSuggestion: boolean | undefined; readonly response: undefined | Promise; readonly nEditsSuggested: number | undefined; readonly lineDistanceToMostRecentEdit: number | undefined; readonly nextEditLogprob: number | undefined; readonly noNextEditReasonKind: string | undefined; readonly noNextEditReasonMessage: string | undefined; readonly nextCursorPrediction: { nextCursorLineError: string | undefined; /** nextCursorLineNumber - currentCursorLineNumber */ nextCursorLineDistance: number | undefined; isCrossFile: boolean | undefined; }; readonly xtabAggressivenessLevel: string | undefined; readonly xtabUserHappinessScore: number | undefined; /** The raw user-facing aggressiveness setting value (only set when user changed from default) */ readonly userAggressivenessSetting: string | undefined; readonly editIntent: string | undefined; readonly editIntentParseError: string | undefined; readonly cursorJumpModelName: string | undefined; readonly cursorJumpPrompt: string | undefined; readonly cursorJumpResponse: string | undefined; readonly nDiffsInPrompt: number | undefined; readonly promptSectionTokens: PromptSectionTokenCounts | undefined; readonly nNeighborSnippetsComputed: number | undefined; readonly nNeighborSnippetsInPrompt: number | undefined; /** JSON-encoded array of original input indices of snippets included in the prompt. */ readonly neighborSnippetIndicesInPrompt: string | undefined; readonly lintErrors: string | undefined; readonly terminalOutput: string | undefined; readonly similarFilesContext: Promise | undefined; } export type FetchResultWithStats = { readonly ttft: number | undefined; readonly response: FetchResponse; readonly fetchTime: number; readonly fetchResult: ChatFetchResponseType; }; export declare class StatelessNextEditTelemetryBuilder { readonly startTime: number; readonly requestUuid: string; /** * It takes a request to automatically capture some properties from the request. */ constructor(headerRequestId: string); build(result: Result): IStatelessNextEditTelemetry; private _logProbThreshold; setLogProbThreshold(logProbThreshold: number): this; private _mergeConflictExpanded; setMergeConflictExpanded(mergeConflictExpanded: 'normal' | 'only'): this; private _hadLowLogProbSuggestion; setHadLowLogProbSuggestion(hadLowLogProbSuggestions: boolean): this; private _nLinesOfCurrentFileInPrompt; setNLinesOfCurrentFileInPrompt(nLines: number): this; private _modelName; setModelName(modelName: string): this; private _prompt; setPrompt(prompt: Raw.ChatMessage[]): this; private _isCursorAtLineEnd; setIsCursorAtLineEnd(isCursorAtLineEnd: boolean): this; private _isInlineSuggestion; setIsInlineSuggestion(isInlineSuggestion: boolean): this; private _debounceTime; setDebounceTime(debounceTime: number): this; private _artificialDelay; setArtificialDelay(artificialDelay: number): this; private _fetchStartedAt; setFetchStartedAt(): this; get fetchStartedAt(): number | undefined; private _response; setResponse(response: Promise<{ ttft: number | undefined; response: FetchResponse; }>): this; private _cursorJumpModelName; setCursorJumpModelName(modelName: string | undefined): this; private _cursorJumpPrompt; setCursorJumpPrompt(prompt: Raw.ChatMessage[] | undefined): this; private _cursorJumpResponse; setCursorJumpResponse(response: string | undefined): this; private _nextEditLogProb; setNextEditLogProb(logProb: number): this; private _nEditsSuggested; setNEditsSuggested(nEditsSuggested: number): this; private _lineDistanceToMostRecentEdit; setLineDistanceToMostRecentEdit(distanceToMostRecentEdit: number): this; private _nextCursorPrediction; setNextCursorLineError(error: string): this; /** * nextCursorLineNumber - currentCursorLineNumber */ setNextCursorLineDistance(distance: number): this; setNextCursorIsCrossFile(isCrossFile: boolean): this; private _xtabAggressivenessLevel; setXtabAggressivenessLevel(level: string): this; private _xtabUserHappinessScore; setXtabUserHappinessScore(score: number): this; private _userAggressivenessSetting; setUserAggressivenessSetting(setting: string): this; private _editIntent; setEditIntent(editIntent: string): this; private _editIntentParseError; setEditIntentParseError(error: string): this; private _nDiffsInPrompt; setNDiffsInPrompt(n: number): this; private _promptSectionTokens; setPromptSectionTokens(counts: PromptSectionTokenCounts): this; private _nNeighborSnippetsComputed; setNNeighborSnippetsComputed(n: number): this; private _nNeighborSnippetsInPrompt; setNNeighborSnippetsInPrompt(n: number): this; private _neighborSnippetIndicesInPrompt; setNeighborSnippetIndicesInPrompt(indices: readonly number[]): this; private _lintErrors; setLintErrors(lintErrors: string): this; private _terminalOutput; setTerminalOutput(terminalOutput: string): this; private _similarFilesContext; setSimilarFilesContext(similarFilesContext: Promise): this; private _modelConfig; setModelConfig(modelConfig: string): this; } //# sourceMappingURL=statelessNextEditProvider.d.ts.map