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 { DebugRecorderBookmark } from './debugRecorderBookmark';
import { InlineEditRequestLogContext } from './inlineEditLogContext';
import { IXtabHistoryEntry } from './workspaceEditTracker/nesXtabHistoryTracker';
export type EditStreaming = AsyncGenerator<StreamedEdit, NoNextEditReason, void>;
export declare class WithStatelessProviderTelemetry<T> {
    readonly v: T;
    readonly telemetryBuilder: IStatelessNextEditTelemetry;
    constructor(v: T, telemetryBuilder: IStatelessNextEditTelemetry);
}
export type EditStreamingWithTelemetry = AsyncGenerator<WithStatelessProviderTelemetry<StreamedEdit>, WithStatelessProviderTelemetry<NoNextEditReason>, 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;
};
export type PushEdit = (edit: Result<StreamedEdit, NoNextEditReason>) => 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<TFirstEdit = any> {
    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<Result<TFirstEdit, NoNextEditReason>>;
    readonly expandedEditWindowNLines: number | undefined;
    readonly isSpeculative: boolean;
    readonly logContext: InlineEditRequestLogContext;
    readonly recordingBookmark: DebugRecorderBookmark | undefined;
    readonly recording: LogEntry[] | undefined;
    readonly providerRequestStartDateTime: number | undefined;
    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<StatelessNextEditResult>;
    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<Result<TFirstEdit, NoNextEditReason>>, expandedEditWindowNLines: number | undefined, isSpeculative: boolean, logContext: InlineEditRequestLogContext, recordingBookmark: DebugRecorderBookmark | undefined, recording: LogEntry[] | undefined, providerRequestStartDateTime: number | undefined);
    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<void, NoNextEditReason>;
    readonly telemetry: IStatelessNextEditTelemetry;
    static noEdit(reason: NoNextEditReason, telemetryBuilder: StatelessNextEditTelemetryBuilder): StatelessNextEditResult;
    static streaming(telemetryBuilder: StatelessNextEditTelemetryBuilder): StatelessNextEditResult;
    constructor(nextEdit: Result<void, NoNextEditReason>, telemetry: IStatelessNextEditTelemetry);
}
export interface IStatelessNextEditTelemetry {
    readonly hadStatelessNextEditProviderCall: boolean;
    readonly statelessNextEditProviderDuration: number;
    readonly isCursorAtEndOfLine: boolean | undefined;
    readonly isInlineSuggestion: boolean | undefined;
    readonly nLinesOfCurrentFileInPrompt: number | undefined;
    readonly modelName: string | 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<FetchResultWithStats>;
    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 diffTokensInPrompt: number | 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<string | undefined> | undefined;
    readonly modelConfig: string | undefined;
}
export type FetchResultWithStats = {
    readonly ttft: number | undefined;
    readonly response: FetchResponse<string>;
    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<void, NoNextEditReason>): 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<string>;
    }>): 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 _diffTokensInPrompt;
    setDiffTokensInPrompt(n: number): 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<string | undefined>): this;
    private _modelConfig;
    setModelConfig(modelConfig: string): this;
}
//# sourceMappingURL=statelessNextEditProvider.d.ts.map