Skip to content

NES: cache cross-file suggestions under the active document#323150

Merged
ulugbekna merged 2 commits into
mainfrom
ulugbekna-nes-cross-file-caching
Jun 27, 2026
Merged

NES: cache cross-file suggestions under the active document#323150
ulugbekna merged 2 commits into
mainfrom
ulugbekna-nes-cross-file-caching

Conversation

@ulugbekna

Copy link
Copy Markdown
Contributor

What

Extends Next Edit Suggestion (NES) caching to support cross-file suggestions — a suggestion the model returns for a document other than the one being edited.

Previously a cross-file suggestion was cached only under the target document's content (B(content) → edit), so it could only be re-served from cache after the user navigated to B. This change additionally caches it under the active document:

A(content + edit window) → edit-in-B

so the cross-file suggestion can be re-served from cache while the cursor is still in A — the same place it was produced.

How

  • Cache (nextEditCache.ts)CachedEdit/CachedEditOpts gain targetDocId? (the document the edit applies to, when different from the key document) and targetDocumentBeforeEdit? (a snapshot of that document's content the edit's offsets index into). The cursor-distance rejection is skipped for cross-file entries (their edit is in the target's coordinate space), while edit-window gating — which is in the active document's coordinates — is kept.

  • Provider write path (nextEditProvider.ts) — when the first streamed edit targets a different document, a small helper also stores the A‑keyed cross-file entry (exact content match only, never rebased). At stream end the active document is no longer cached as "no edit" when a cross-file entry was just stored under the same key, which would otherwise clobber it. Applied to both the normal and speculative paths.

  • Provider read path (nextEditProvider.ts) — a cross-file cache hit is served only while its target document is open and byte-identical to the stored snapshot. Otherwise the hit is treated as a cache miss → fresh fetch, rather than serving a misplaced edit or getting stuck re-serving a dead entry until the active document changes.

This is always on (no config flag).

Two invalidation layers

  1. Default config — editing the target document already purges cross-document cache entries (the existing InlineEditsTriggerOnEditorChangeAfterSeconds purge, default 10).
  2. Read-path validity guard — additionally covers the closed-target case (closing isn't an edit, so no purge) and the purge-disabled configuration.

Tests

7 cross-file tests in nextEditProviderCaching.spec.ts, assertions are behavioral (served edit + provider call-count, deterministically waiting for the first request's stream-end before re-requesting):

  • re-serves on a 2nd trigger in A and survives the no-suggestions stream-end (no clobber);
  • re-serves within / refetches outside the cached edit window;
  • refetches when the target document is closed;
  • control: with the purge disabled and the target unchanged, re-serves from cache (isolates the guard);
  • refetches when the target changed — once with the purge disabled (guard fires) and once under the default config (purge fires).

Validation

  • nextEditProviderCaching.spec.ts: 11/11 pass; broader NES suite: 89 pass / 2 pre-existing skips.
  • Typecheck (tsgo --noEmit) and eslint clean on all changed files.

Out of scope

  • Rebasing the active-document-keyed entry across edits in the active document (exact-match only).
  • Hardening the fresh cross-file path against the target changing in-flight (pre-existing; subsequent re-serves are already protected by the new guard).

When the model returns a Next Edit Suggestion for a document other than
the one being edited (cross-file NES), it was only cached under the target
document, so it could not be re-served until the user navigated there.
Also cache an `activeDoc (content + edit window) -> edit-in-target`
association so the suggestion can be re-served from cache while the cursor
is still in the active document.

A cross-file entry is served only while its target document is open and
byte-identical to the snapshot the edit's offsets index into; otherwise the
read path treats it as a cache miss and refetches, rather than serving a
misplaced edit or getting stuck re-serving a dead entry until the active
document changes. At stream end the active document is no longer cached as
"no edit" when a cross-file entry was just stored under the same key, which
would otherwise clobber it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 26, 2026 15:42
@ulugbekna ulugbekna marked this pull request as ready for review June 26, 2026 15:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends Next Edit Suggestion (NES) caching to better support cross-file suggestions by additionally caching cross-file edits under the active document key, and adding a read-path validity guard to ensure cross-file cache hits are only served when the target document is open and byte-identical to the stored snapshot.

Changes:

  • Extend cache entry metadata (targetDocId, targetDocumentBeforeEdit) to represent cross-file edits and safely validate them at read time.
  • Update NextEditProvider to (a) cache cross-file edits under the active document key, and (b) avoid clobbering that entry with a “no suggestions” cache write at stream end.
  • Add a dedicated cross-file caching test suite covering cache re-serve, edit-window gating, closed-target behavior, and stale-target invalidation paths.
Show a summary per file
File Description
extensions/copilot/src/extension/inlineEdits/test/node/nextEditProviderCaching.spec.ts Adds cross-file caching scenarios and assertions for re-serve vs refetch behavior.
extensions/copilot/src/extension/inlineEdits/node/nextEditProvider.ts Implements active-document-keyed caching for cross-file edits plus read-path validity checks and stream-end clobber avoidance.
extensions/copilot/src/extension/inlineEdits/node/nextEditCache.ts Extends cached edit metadata to carry cross-file target info and adjusts cursor-distance rejection behavior for cross-file entries.

Review details

  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Low

Tear down the NextEditProvider (which registers autoruns/watchers on
openDocuments) and both documents at the end of each cross-file scenario
run so the tests are self-contained and do not accumulate observers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ulugbekna ulugbekna merged commit 4fc2b33 into main Jun 27, 2026
29 checks passed
@ulugbekna ulugbekna deleted the ulugbekna-nes-cross-file-caching branch June 27, 2026 12:02
@vs-code-engineering vs-code-engineering Bot added this to the 1.127.0 milestone Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants