Skip to content

Conversation

@bstee615
Copy link
Member

@bstee615 bstee615 commented Jan 26, 2026

This adds a new prompting strategy that extends Xtab275 with edit intent tag parsing. The model returns an edit_intent tag indicating confidence level (no_edit, low, medium, high), which is then filtered against the user's aggressiveness level.

See Personalized XTab: edit intent (#3144) for details. This PR is required in order to flight the edit intent model.

Model can output tags (<|edit_intent|>no_edit|low|medium|high<|/edit_intent|>) or short names (N|L|M|H) to save tokens, which will be parsed strictly from the first line of the response. The first model we've trained will output tags.

Changes:

  • Add EditIntent enum and namespace with parsing and filtering logic
  • Add EditWindowWithEditIntent response format
  • Add Xtab275EditIntent prompting strategy
  • Implement parseEditIntentFromStream in xtabProvider
  • Add editIntent telemetry field
  • Add comprehensive unit tests for EditIntent
  • Add short names for edit tags, which will be used later.

bstee615 and others added 15 commits January 26, 2026 20:07
This adds a new prompting strategy that extends Xtab275 with edit intent
tag parsing. The model returns an edit_intent tag indicating confidence
level (no_edit, low, medium, high), which is then filtered against the
user's aggressiveness level.

Filtering logic:
- no_edit: Never show
- low intent: Show for all aggressiveness levels
- medium intent: Show for low/medium aggressiveness
- high intent: Only show for low aggressiveness

Changes:
- Add EditIntent enum and namespace with parsing and filtering logic
- Add EditWindowWithEditIntent response format
- Add Xtab275EditIntent prompting strategy
- Implement parseEditIntentFromStream in xtabProvider
- Add editIntent telemetry field
- Add comprehensive unit tests for EditIntent

Co-authored-by: GitHub Copilot <noreply@github.com>
…t short-circuits to skip the rest of the stream
@bstee615
Copy link
Member Author

Manual test

User config

  "github.copilot.chat.advanced.inlineEdits.xtabProvider.modelConfiguration": {
    "modelName": "copilot-nes-oct",
    "promptingStrategy": "xtab275EditIntent",
    "includeTagsInCurrentFile": false,
  },
Traces from manual test # NoEdit (filtered out -- rough speedup from 1947ms to 311-426 ms, assuming NoEdit would consume an equal number of tokens and not accounting for speculative decoding)

Timeline (nested call hierarchy):
────────────────────────────────────────────────────────────
[  0ms] ├── [NES]
        │   │   │   │   ↳ invoked with trigger id = uuid = c90c2ca3-50a5-4ad1-b34c-ceb0eb52462d, reason = selectionChange
[  0ms] │   ├── [NextEditProvider]
        │   │   │   │   ↳ fetching next edit with shouldExpandEditWindow=false
[  0ms] │   │   ├── [9fdd]
        │   │   │   │   ↳ awaiting firstEdit promise
[  4ms] │   │   │   ├── [_getNextEdit]
        │   │   │   │   │   │   │   │   ↳ Debouncing for cursor NOT at end of line
[  4ms] │   │   │   │   ├── [fetchNextEdit]
        │   │   │   │   │   │   │   │   ↳ Using default nLinesBelow: 5
[  6ms] │   │   │   │   │   ├── [_executeNewNextEditRequest]
        │   │   │   │   │   │   │   │   ↳ Debouncing for 95 ms
[423ms] │   │   │   │   │   │   ├── [XtabProvider]
        │   │   │   │   │   │   │   │   │   │   ↳ Parsed edit_intent from first line: "no_edit" -> no_edit
[423ms] │   │   │   │   │   │   │   ├── [doGetNextEditWithSelection]
        │   │   │   │   │   │   │   │   │   │   ↳ Filtered out edit due to edit intent "no_edit" with aggressiveness "medium"
[424ms] │   │   │   │   │   │   ├── [pushEdit]
        │   │   │   │   │   │   │   ↳ processing edit #0 (starts at 0)
[424ms] │   │   │   │   │   │   │   ↳ no edit, reason: filteredOut
[425ms] │   │   │   │   ↳ resolved firstEdit promise
[425ms] │   │   │   │   ↳ First edit latency: 426 ms
[425ms] │   │   │   │   ↳ failed to fetch next edit filteredOut:editIntent:no_edit aggressivenessLevel:medium
[425ms] │   │   │   │   ↳ had no edit
[425ms] │   │   │   │   │   │   ├── [XtabProvider]
        │   │   │   │   │   │   │   │   │   │   ↳ Line 0 emitted with latency 310.2620999999999 ms
[428ms] │   │   │   │   │   │   │   ├── [doGetNextEditWithSelection]
        │   │   │   │   │   │   │   │   │   │   ↳ Line 1 emitted with latency 313.27710000000116 ms
[429ms] │   │   │   │   │   │   │   │   ├── [streamEditsWithFiltering]
        │   │   │   │   │   │   │   │   │   │   ↳ Line 2 emitted with latency 314.22490000000107 ms

Medium confidence + Medium aggressiveness (applied)


Timeline (nested call hierarchy):
────────────────────────────────────────────────────────────
[   0ms] ├── [NES]
         │   │   │   │   ↳ invoked with trigger id = undefined
[   1ms] │   ├── [NextEditProvider]
         │   │   │   │   ↳ fetching next edit with shouldExpandEditWindow=false
[   2ms] │   │   ├── [9306]
         │   │   │   │   ↳ awaiting firstEdit promise
[  10ms] │   │   │   ├── [_getNextEdit]
         │   │   │   │   │   │   │   │   ↳ Debouncing for cursor NOT at end of line
[  11ms] │   │   │   │   ├── [fetchNextEdit]
         │   │   │   │   │   │   │   │   ↳ Using default nLinesBelow: 5
[  16ms] │   │   │   │   │   ├── [_executeNewNextEditRequest]
         │   │   │   │   │   │   │   │   ↳ Debouncing for 90 ms
[1463ms] │   │   │   │   │   │   ├── [XtabProvider]
         │   │   │   │   │   │   │   │   │   │   ↳ Parsed edit_intent from first line: "medium" -> medium
[1464ms] │   │   │   │   │   │   │   ├── [doGetNextEditWithSelection]
         │   │   │   │   │   │   │   │   │   │   ↳ starting to diff stream against edit window lines with latency 1177.0332000000017 ms
[1465ms] │   │   │   │   │   │   │   │   ├── [streamEditsWithFiltering]
         │   │   │   │   │   │   │   │   │   │   ↳ Line 0 emitted with latency 1178.072500000002 ms
[1467ms] │   │   │   │   │   │   │   │   │   ├── [streamEdits]
         │   │   │   │   │   │   │   │   │   │   ↳ Line 1 emitted with latency 1180.5799000000006 ms
[1469ms] │   │   │   │   │   │   │   │   │   │   ↳ Line 2 emitted with latency 1181.7515000000021 ms
[3221ms] │   │   │   │   │   │   │   │   │   │   ↳ ResponseProcessor streamed edit #0 with latency 2934.4310000000005 ms
[3441ms] │   │   │   │   │   │   │   │   │   │   ↳ Ran diff for #0 with latency 3154.041100000002 ms
[3441ms] │   │   │   │   │   │   │   │   │   │   ↳ extracting edit #0: [3,5)->["    return a"]
[3443ms] │   │   │   │   │   │   │   │   │   ↳ Yielding an edit: [3,5)->["    return a"]
[3443ms] │   │   │   │   │   │   ├── [pushEdit]
         │   │   │   │   │   │   │   ↳ processing edit #0 (starts at 0)
[3443ms] │   │   │   │   │   │   │   ↳ resetting shouldExpandEditWindow to false due to receiving an edit
[3444ms] │   │   │   │   │   │   │   ↳ populated cache for 0
[3444ms] │   │   │   │   │   │   │   ↳ resolving firstEdit promise
[3445ms] │   │   │   │   ↳ resolved firstEdit promise
[3445ms] │   │   │   │   ↳ First edit latency: 1947 ms
[3445ms] │   │   │   │   ↳ fetch succeeded
[3445ms] │   │   │   │   ↳ cancelled
[3447ms] │   │   │   │   │   │   │   ↳ processing edit #1 (starts at 0)
[3447ms] │   │   │   │   │   │   │   ↳ 1 edits returned

Low confidence + Med aggressiveness (filtered out)

Timeline (nested call hierarchy):
────────────────────────────────────────────────────────────
[  0ms] ├── [NES]
        │   │   │   │   ↳ invoked with trigger id = uuid = f2d8b5bd-df25-4a1d-a2f3-07ea5ce715ad, reason = selectionChange
[  0ms] │   ├── [NextEditProvider]
        │   │   │   │   ↳ fetching next edit with shouldExpandEditWindow=false
[  0ms] │   │   ├── [c58b]
        │   │   │   │   ↳ awaiting firstEdit promise
[  5ms] │   │   │   ├── [_getNextEdit]
        │   │   │   │   │   │   │   │   ↳ Debouncing for cursor NOT at end of line
[  6ms] │   │   │   │   ├── [fetchNextEdit]
        │   │   │   │   │   │   │   │   ↳ Using default nLinesBelow: 5
[  9ms] │   │   │   │   │   ├── [_executeNewNextEditRequest]
        │   │   │   │   │   │   │   │   ↳ Debouncing for 93 ms
[310ms] │   │   │   │   │   │   ├── [XtabProvider]
        │   │   │   │   │   │   │   │   │   │   ↳ Parsed edit_intent from first line: "low" -> low
[310ms] │   │   │   │   │   │   │   ├── [doGetNextEditWithSelection]
        │   │   │   │   │   │   │   │   │   │   ↳ Filtered out edit due to edit intent "low" with aggressiveness "medium"
[311ms] │   │   │   │   │   │   ├── [pushEdit]
        │   │   │   │   │   │   │   ↳ processing edit #0 (starts at 0)
[311ms] │   │   │   │   │   │   │   ↳ no edit, reason: filteredOut
[311ms] │   │   │   │   ↳ resolved firstEdit promise
[311ms] │   │   │   │   ↳ First edit latency: 311 ms
[311ms] │   │   │   │   ↳ failed to fetch next edit filteredOut:editIntent:low aggressivenessLevel:medium
[311ms] │   │   │   │   ↳ had no edit
[311ms] │   │   │   │   │   │   ├── [XtabProvider]
        │   │   │   │   │   │   │   │   │   │   ↳ Line 0 emitted with latency 204.49589999999807 ms
[395ms] │   │   │   │   │   │   │   ├── [doGetNextEditWithSelection]
        │   │   │   │   │   │   │   │   │   │   ↳ Line 1 emitted with latency 287.5645999999979 ms
[396ms] │   │   │   │   │   │   │   │   ├── [streamEditsWithFiltering]
        │   │   │   │   │   │   │   │   │   │   ↳ Line 2 emitted with latency 288.9424999999974 ms

@bstee615 bstee615 marked this pull request as ready for review January 26, 2026 23:57
Copilot AI review requested due to automatic review settings January 26, 2026 23:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request adds a new prompting strategy Xtab275EditIntent that extends the Xtab275 strategy with edit intent tag parsing and filtering. The model returns an <|edit_intent|> tag indicating its confidence level (no_edit, low, medium, high), which is then filtered against the user's aggressiveness level to determine whether to show the edit suggestion.

Changes:

  • Introduces EditIntent enum and namespace with parsing logic and confidence-based filtering
  • Adds EditWindowWithEditIntent response format for the new prompting strategy
  • Implements parseEditIntentFromStream function to extract edit intent tags from model responses
  • Extends telemetry with editIntent and editIntentParseError fields
  • Provides comprehensive unit tests covering all edge cases and integration scenarios

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/platform/inlineEdits/common/dataTypes/xtabPromptOptions.ts Adds EditIntent enum with filtering logic and Xtab275EditIntent prompting strategy
src/platform/inlineEdits/common/statelessNextEditProvider.ts Adds telemetry fields for edit intent and parse errors
src/extension/xtab/node/xtabProvider.ts Implements parseEditIntentFromStream parsing function and integrates filtering logic into provider
src/extension/xtab/common/promptCrafting.ts Updates postscript generation to handle Xtab275EditIntent strategy
src/extension/xtab/test/node/editIntent.spec.ts Adds comprehensive unit tests for all edit intent functionality
src/platform/inlineEdits/common/inlineEditLogContext.ts Fixes trailing comma for consistency

@bstee615
Copy link
Member Author

CC @ulugbekna, could you please review this PR? 🙏

@connor4312 connor4312 assigned ulugbekna and unassigned connor4312 Jan 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants