import { DocumentId } from '../../../platform/inlineEdits/common/dataTypes/documentId'; import { StatelessNextEditRequest } from '../../../platform/inlineEdits/common/statelessNextEditProvider'; import { ILogger } from '../../../platform/log/common/logService'; import { Disposable } from '../../../util/vs/base/common/lifecycle'; import { CachedOrRebasedEdit } from './nextEditCache'; import { NextEditResult } from './nextEditResult'; /** * Reasons why a speculative request was cancelled. Recorded on the request's * log context so each cancellation has an attributable cause. */ export declare const enum SpeculativeCancelReason { /** The originating suggestion was rejected by the user. */ Rejected = "rejected", /** The originating suggestion was dismissed without being superseded. */ IgnoredDismissed = "ignoredDismissed", /** A new fetch is starting whose `(docId, postEditContent)` doesn't match. */ Superseded = "superseded", /** A newer speculative is being installed in this slot. */ Replaced = "replaced", /** The user's edits moved off the type-through trajectory toward `postEditContent`. */ DivergedFromTrajectoryForm = "divergedFromTrajectoryForm", DivergedFromTrajectoryPrefix = "divergedFromTrajectoryPrefix", DivergedFromTrajectoryMiddle = "divergedFromTrajectoryMiddle", DivergedFromTrajectorySuffix = "divergedFromTrajectorySuffix", /** `clearCache()` was invoked. */ CacheCleared = "cacheCleared", /** The target document was removed from the workspace. */ DocumentClosed = "documentClosed", /** The provider was disposed. */ Disposed = "disposed" } export interface SpeculativePendingRequest { readonly request: StatelessNextEditRequest; readonly docId: DocumentId; readonly postEditContent: string; /** preEditDocument[0..editStart] — the doc text before the edit window. */ readonly trajectoryPrefix: string; /** preEditDocument[editEnd..] — the doc text after the edit window. */ readonly trajectorySuffix: string; /** The replacement text the user would type to reach `postEditContent`. */ readonly trajectoryNewText: string; } export interface ScheduledSpeculativeRequest { readonly suggestion: NextEditResult; readonly headerRequestId: string; } /** * Owns the lifecycle of NES speculative requests: * * - the in-flight `pending` speculative (the bet on a specific post-accept document state) * - the `claimed` speculatives, already picked up by a `getNextEdit` caller but kept * discoverable so concurrent callers join them instead of duplicating the request * - the `scheduled` speculative deferred until its originating stream completes * * Centralizes cancellation with typed reasons so every triggered cancellation * (reject, supersede, doc-close, trajectory divergence, dispose, ...) goes through * one path and is logged on the request's log context. */ export declare class SpeculativeRequestManager extends Disposable { private readonly _logger; private _pending; private _scheduled; /** * Speculatives that a `getNextEdit` caller has claimed and is awaiting. * * They stay discoverable here until they settle so that *concurrent* callers for the * same post-edit state join the same request instead of issuing a duplicate one. Keyed * by request identity: several may be in flight at once (e.g. one per document), and * evicting one on the arrival of another would reintroduce the duplicate-request bug. */ private readonly _claimed; constructor(_logger: ILogger); get pending(): SpeculativePendingRequest | null; /** Replaces the current pending speculative; cancels the prior one as `Replaced`. */ setPending(req: SpeculativePendingRequest): void; /** * Detaches the pending speculative without cancelling — the caller is consuming it — * and keeps it discoverable via {@link findClaimed} until it settles. */ claimPending(): void; /** Returns the first claimed speculative matching `predicate`, if any. */ findClaimed(predicate: (req: SpeculativePendingRequest) => boolean): SpeculativePendingRequest | undefined; private _releaseClaimed; schedule(s: ScheduledSpeculativeRequest): void; clearScheduled(): void; /** * Removes and returns the scheduled entry iff its `headerRequestId` matches. * Used by the streaming path so that each stream only ever consumes its own * schedule, never another stream's. */ consumeScheduled(headerRequestId: string): ScheduledSpeculativeRequest | null; cancelAll(reason: SpeculativeCancelReason): void; /** Cancels the pending speculative iff `(docId, postEditContent)` doesn't match. */ cancelIfMismatch(docId: DocumentId, postEditContent: string, reason: SpeculativeCancelReason): void; /** Cancels the pending and clears any scheduled targeting this document. */ onDocumentClosed(docId: DocumentId): void; /** * Trajectory check. The pending speculative is alive iff the current document * value is a *type-through prefix* toward the speculative's `postEditContent`: * * cur === trajectoryPrefix + middle + trajectorySuffix * where middle is some prefix of trajectoryNewText * * If not, the user's edits cannot reach `postEditContent` via continued typing * and the speculative will never be consumed — cancel now. */ onActiveDocumentChanged(docId: DocumentId, currentDocValue: string): void; private _cancelPending; /** * Hard invalidation for claimed speculatives. * * Claimed speculatives deliberately survive the "nobody will want this anymore" reasons * ({@link SpeculativeCancelReason.Replaced}, `Superseded`, `Rejected`, `IgnoredDismissed`, * trajectory divergence): they have a live consumer awaiting them, and their lifetime is * already governed by `liveDependentants` plus that consumer's cancellation token. * * They must not survive reasons that invalidate the *result itself* — a cleared cache, a * closed document, or disposal — since a later caller could otherwise join a request built * on now-stale state. */ invalidateClaimed(reason: SpeculativeCancelReason, filter?: (req: SpeculativePendingRequest) => boolean): void; private _cancelRequest; dispose(): void; } //# sourceMappingURL=speculativeRequestManager.d.ts.map