* nes: dedupe NextEditProvider streamed-edit handling into shared helper
Extract the per-edit rebase+cache logic shared by the regular fetch path
(`_executeNewNextEditRequest`) and the speculative path
(`_runSpeculativeProviderCall`) into a single `_cacheStreamedEdit` method.
Both loops previously open-coded the same convert -> rebase -> compose ->
setKthNextEdit -> cross-file cache pipeline, which had started to drift.
Also:
- extract the inline doc-state type into a named `DocState` interface and
mark the non-reassigned fields `readonly`
- reuse the existing exported `StreamedEdit` type instead of a local
duplicate
Behavior-preserving: the only differences are trace-level log messages.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: rename _cacheStreamedEdit to _rebaseAndCacheStreamedEdit
The method does more than cache: it also rebases the streamed edit onto the
edits applied so far and mutates the per-doc accumulators. The new name
reflects that wider responsibility.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: pass _rebaseAndCacheStreamedEdit args as an options object
Replace the nine positional parameters with a single typed
RebaseAndCacheStreamedEditArgs object and group the active-document fields
(id, contents, cursorOffset) under `activeDoc`. This removes the
call-site ambiguity of several same-typed/optional positional arguments.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: let _rebaseAndCacheStreamedEdit own docContents advancement
Previously the helper mutated editsSoFar/nextEdits/patchIndices and the
cache, but left advancing the target document's running `docContents` to
each caller (a foot-gun: a future caller could forget it, desyncing the
cache key from subsequent edits).
The helper now owns the full per-edit state transition: it snapshots the
pre-edit contents, populates the cache against that snapshot, then advances
`docContents`. The snapshot is returned as `docContentsBeforeEdit` so the
regular path can still log the first edit against the pre-edit contents.
`targetDocState` is no longer returned, so callers can't mutate it.
Behavior-preserving.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: drop redundant targetDocument fallback in _rebaseAndCacheStreamedEdit
StreamedEdit.targetDocument is a required DocumentId, so the
`?? activeDoc.id` fallback was dead code that could mislead readers into
thinking targetDocument may be omitted. Addresses PR review feedback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Only show completion feedback command for paid users
The 'Send Copilot Completion Feedback' command is attached to every
inline completion list, which surfaces the feedback button for all
users including free and unauthenticated ones. This has been a source
of low-signal issue-tracker spam.
Gate the command so it is only offered when the Copilot token belongs
to a paid user (not free and not no-auth).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Fix completion feedback token shadowing
Rename the Copilot auth token local so it does not shadow the cancellation token used by inline completion generation.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Pass the Copilot CLI session label through the Agents Window delete flow into the Git worktree removal confirmation so dirty worktree prompts show which session owns the worktree.\n\nFixes #324220\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Kimi models (kimi-k2.6, kimi-k2.7-code) require temperature=1 and
top_p=0.95. Override these in customizeCapiBody so the values are
forced on all outbound CAPI requests regardless of what the client
would otherwise send, across agent/ask/edit modes and streaming and
non-streaming paths.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add a regression test asserting the routing decision surfaced to the UI (consumeLastRoutingDecision, which drives the 'Routed to <model>' explainability label) resolves to chosen_model, matching the served endpoint shown in the response footer. This locks in that the top label and bottom footer cannot diverge.
Auto mode resolved the pseudo-model by picking candidate_models[0] (the
pre-experiment ranked list) and never consumed chosen_model, the router's
authoritative pick after server-side re-ranking (e.g. Cost Sorting). Per the
auto-intent-service contract (docs/integrators_onboarding.md), clients must
"use chosen_model for the upcoming chat call, and use candidate_models as the
ordered fallback list". The CLI already does this; VS Code did not, so VS Code
was invisible to the Cost Sorting experiment and sent a different model than
Auto Intent chose (e.g. router chose GPT 5.4 Mini, VS Code sent GPT 5.3 Codex).
Prefer chosen_model (resolved against known endpoints) and fall back to the
ordered candidate_models list only when chosen_model is absent or unresolvable.
Also report chosen_model as candidateModel in the automode.routerModelSelection
telemetry so router-pick vs actual comparisons are meaningful.
Existing tests hid the bug because every fixture set
chosen_model === candidate_models[0]. Added regression tests that decouple the
two fields.
* nes: fold currentFile budgeting into the global budget cascade
Under the opt-in global budget experiment, the current file now draws its
clip budget from the shared pool (its `shares.currentFile` slice of
`totalTokens`) and donates whatever it does not use to the cascade as the
initial surplus. When the global budget is disabled (prod default) behavior
is byte-identical, and the new defaults (totalTokens 8000, shares in eighths)
reproduce today's per-part `maxTokens` caps exactly.
- xtabPromptOptions: add `GlobalBudgetSharePart`, `currentFileBudget()` and
`validate()`; grow `shares` to include `currentFile`; bump
`DEFAULT_TOTAL_TOKENS` to 8000 and rebalance `DEFAULT_SHARES`.
- promptCrafting: seed the cascade's initial surplus from the current file's
leftover budget; delegate validation to the namespace helper.
- xtabProvider: size and clip the current file from the pool and compute the
surplus, gated on `globalBudget` being defined.
- Tests: volume-neutral invariant, `currentFileBudget`/`validate` units, and
provider-level regression + new-behavior coverage.
- Docs: rewrite globalBudgetCascade.md for the seeded-surplus design.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: collapse global-budget settings into a single exp-driven JSON string
Replace the two experiment-driven global-budget settings
(globalBudget.enabled boolean + globalBudget.totalTokens number) with a
single JSON-encoded string setting, modelled after modelConfigurationString,
that defines totalTokens, order, and shares together.
- configurationService: remove InlineEditsXtabGlobalBudgetEnabled and
InlineEditsXtabGlobalBudgetTotalTokens; add InlineEditsXtabGlobalBudget
(string | undefined, ExperimentBased, default undefined).
- xtabPromptOptions: add GlobalBudgetOptions.VALIDATOR (all top-level fields
optional; shares must be complete when present) and a pure
GlobalBudgetOptions.fromConfigString(): Result<GlobalBudgetOptions, string>
that JSON-parses, structurally validates, merges over the defaults, then
runs the semantic validate(). Never throws.
- xtabProvider: inject ITelemetryService; resolve the budget via
getGlobalBudget(), returning undefined (disabled, identical to prod) when
the string is unset/empty/invalid and emitting incorrectNesGlobalBudgetConfig
telemetry on parse/validation failure.
- Tests: migrate the provider global-budget tests to the JSON string and add
fromConfigString unit tests.
- Docs: rewrite the globalBudgetCascade.md Wiring section and migration note.
No regression: an unset string keeps the byte-identical legacy path. '{}'
enables the budget with the volume-neutral defaults; {"totalTokens":N} only
overrides the pool size.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: clip the current file last under a global budget to reuse cascade leftover
Under a global budget the current file is now clipped LAST, sized to its base
share plus whatever the budget cascade left unused (`currentFileBudget +
finalSurplus`), so it trims less and reuses leftover budget. The cascade runs
first (seeded with 0, the current file never donates) and is threaded into
`getUserPrompt` via `precomputedCascade` so it renders exactly once.
This replaces the earlier two-mode design: the opt-in `reuseLeftoverForCurrentFile`
flag and the seeded-surplus "donate-forward" path are dropped, along with all
`currentFileBudgetSurplus`/`initialSurplus` threading. Clip-last is now the single
behavior under a global budget. The validator hardening (rejecting non-finite or
negative `totalTokens`/shares) is kept.
No production regression: when `globalBudget` is undefined the current file is
still clipped to its own `currentFile.maxTokens` with the legacy await ordering,
byte-identical to before. The global budget remains experiment-gated and off in
prod.
Tests and globalBudgetCascade.md updated for the clip-last-only behavior.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* nes: address review — restore nLinesOfCurrentFileInPrompt telemetry timing
- xtabProvider: record setNLinesOfCurrentFileInPrompt inside both budget
branches. In the legacy/prod branch the clip happens before the
context-gathering awaits, so the telemetry call is moved back there to
match prod timing exactly (it is still emitted when a request is
cancelled mid-gathering). The clip-last branch records it after the
cascade, as the clip is inherently last there.
- xtabPromptOptions: fix two stale JSDoc blocks that still described the
removed donate-forward behavior; describe clip-last instead.
- globalBudgetCascade.md: correct the conservation bound to T·(Σ shares)
and document the share-sum tolerance (over-allocation ≤ ~1e-3·T).
- promptCrafting.spec: add a cascade test asserting finalSurplus shrinks
as the cascade consumes budget (current file reuses less leftover).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* nes: fix stale DEFAULT_ORDER doc comment to say clip-last
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* nes: rename clipCurrentFileToBudget param to overriddenMaxTokens
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* nes: extract current-file clip + context gathering into a method
Pulls the ~55-line global-budget/legacy if-else out of doGetNextEditWithSelection
into a private gatherContextAndClipCurrentFile method returning
Result<{ clippedTaggedCurrentDoc, areaAroundCodeToEdit, precomputedCascade,
langCtx, neighborSnippets }, NoNextEditReason>. Behavior, clip-first/clip-last
ordering, and nLinesOfCurrentFileInPrompt telemetry timing are unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* nes: recalibrate global-budget defaults to merged currentFile cap (1500)
main (#322382) lowered currentFile.maxTokens 2000->1500, which broke the
global-budget 'volume-neutral defaults' invariant (floor(total*share) must
equal each part's legacy cap). Recalibrate DEFAULT_SHARES to cap/7500 and set
DEFAULT_TOTAL_TOKENS to 7500 (the sum of the merged per-part caps: 1500 + 2000
+ 2000 + 1000 + 1000), so shares still sum to exactly 1 and every part's base
allocation reproduces its cap. finalSurplus stays 6000 (7500 - 1500).
Update dependent specs (literal 8000 -> DEFAULT_TOTAL_TOKENS, stale 2000 cap
comments -> 1500) and the design doc (defaults table, worked examples, effective
caps, ordering caveat, migration note) for T=7500 and currentFile base 1500.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add Responses API cache control markers
* Refactoring code
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Gate Responses API cache breakpoints by model support
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Update @github/copilot and @github/copilot-sdk to version 1.0.67 and 1.0.5-preview.1 respectively
- Updated package.json and package-lock.json in both root and remote directories to reflect the new versions of @github/copilot and @github/copilot-sdk.
- Modified copilotSessionLauncher.ts to include new hooks in the Copilot session configuration.
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* utils: document binarySearch
* nes-datagen: generate training data from continuous recordings
Continuous enhanced telemetry now ships sliding-window recordings that, unlike per-request alternative-action recordings, carry no requestTime. The datagen pipeline needs a point to split each recording into edit history before/after, so this adds a pluggable pivot strategy (starting with Random, selectable via --pivot-strategy) and a new continuous/ pipeline module that replays a recording at the chosen pivot to produce a processed row.
Along the way this consolidates the pipeline's error and index handling: a shared WithRowIndex<T> replaces the ad-hoc { originalRowIndex, ... } pairs, per-record processing returns Result<IProcessedRow, Error> instead of field-presence unions, and failures surface as original Error objects (no string round-tripping). The telemetry sender's continuous payload is now the documented IContinuousRecording type.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* nes-datagen: label alt-action replay errors by originalRowIndex
Address PR review: the alternative-action path mislabeled diagnostics when
earlier records failed to parse.
- processAllRows: push replay errors with the row's true `originalRowIndex`
instead of its position in the filtered `rows` array (parse failures make
`rows` sparse, so the two diverge).
- loadAndProduceProcessedRows: resolve `languageForRow` via an
`originalRowIndex`-keyed Map rather than positional `rows[i]`, matching how
callers pass `e.originalRowIndex`.
- Clarify the `recordCount` doc: it counts successfully-parsed records (parse
failures are counted separately in `parseErrors`).
- Add a regression spec asserting replay errors carry the row index, not the
array position.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Update @github/copilot and related dependencies to version 1.0.66-2
- Bumped @github/copilot to version 1.0.66-2 in package.json and package-lock.json.
- Updated optional dependencies for various platforms to match the new version.
- Adjusted @github/copilot-sdk to version 1.0.5-preview.0.
- Enhanced filtering logic in copilotCLITools.ts to include additional attachment types.
* Enhance attachment rendering in CopilotCLISession with additional GitHub attachment types
* Remove optional suppressResumeEvent property from ICopilotResumeSessionLaunchPlan interface
---------
Co-authored-by: Anthony Kim <62267334+anthonykim1@users.noreply.github.com>
* Make Copilot sanity tests mint their own token instead of using static copilot-token
The Copilot sanity tests resolve their Copilot token via
getOrCreateTestingCopilotTokenManager, which prefers VSCODE_COPILOT_CHAT_TOKEN
(set here from the `copilot-token` Key Vault secret) over GITHUB_OAUTH_TOKEN.
`copilot-token` holds a pre-minted Copilot token that is refreshed out-of-band
by a separate scheduled pipeline. When that refresher broke (the GitHub OAuth
secret it reads was rotated/removed during a security incident), `copilot-token`
silently went stale and expired. The static token manager hands the expired
token to CAPI `/models`, which returns 401, leaving no resolved model and
surfacing the misleading "server did not mark a chat fallback model" error.
Drop the static `copilot-token` so the tests fall through to GITHUB_OAUTH_TOKEN
(`capi-oauth-pipeline-token`) and exchange it for a fresh Copilot token on
demand. This path self-refreshes and removes the dependency on the external
refresher.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-enable sanity tests and surface model-fetch error
- Re-enable the three Copilot sanity tests that were temporarily skipped in
#323684 now that token resolution is fixed.
- Surface the underlying model-fetch error (e.g. an expired-token 401) from
ModelMetadataFetcher resolve methods instead of the misleading
"server did not mark a chat fallback model" message.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Omit reasoning summary instead of sending invalid 'off' value
#323639 disabled Responses API reasoning summaries by hard-coding
`reasoning.summary = 'off'`, but the Responses API only accepts
'concise', 'detailed', or 'auto' (or omitting the field to disable).
Models such as gpt-5.3-codex reject 'off' with HTTP 400
invalid_request_body, which surfaced as failing Copilot sanity tests
once they could reach the model.
Set summary to undefined so the field is omitted (summaries stay
disabled, as intended) and update the unit test accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Decouple reasoning-preserve test from disabled summary
The "should preserve reasoning object when thinking is supported" test
relied on the reasoning summary always being present to keep
body.reasoning defined. Now that the summary is omitted, give the test
model reasoning_effort support so body.reasoning is populated via effort,
which is what the test actually means to verify.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* signing commit
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename capi-oauth secret to capi-oauth-pipeline-token
The capi-oauth Key Vault secret value leaked. Rename the secret
reference to capi-oauth-pipeline-token so that revoking the old
capi-oauth secret cuts off access for any other harness still
pointing at the old name. The new name is also more descriptive of
its purpose (CAPI OAuth token used in the automation pipeline).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add Responses API cache control markers
* Refactoring code
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Gate Responses API cache breakpoints by model support
* Disable Responses API reasoning summaries
* reverting cache commits
* Remove Responses API cache breakpoint handling
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>