nes: fix: allow external users to configure inline edit settings (#330256)

copilot: fix: allow external users to configure inline edit settings

Remove the team-only value restriction from selected hidden advanced inline edit settings while preserving their keys, defaults, validators, and experiment behavior. Add coverage that verifies an external user can configure all ten settings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 97f1135d-4a33-4139-ab2c-9cb8045ece70
This commit is contained in:
Ulugbek Abdullaev
2026-08-11 14:29:23 +00:00
committed by GitHub
co-authored by Copilot
parent ee555d3496
commit a3d4092eef
2 changed files with 56 additions and 10 deletions
@@ -825,10 +825,10 @@ export namespace ConfigKey {
* evicted — it is simply gated until the cursor returns to an
* inline-renderable position.
*/
export const InlineEditsNesMimicGhostTextBehavior = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.nesMimicGhostTextBehavior', ConfigType.ExperimentBased, false, vBoolean());
export const InlineEditsNesMimicGhostTextBehavior = defineSetting<boolean>('chat.advanced.inlineEdits.nesMimicGhostTextBehavior', ConfigType.ExperimentBased, false, vBoolean());
export const InlineEditsXtabProviderUsePrediction = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.usePrediction', ConfigType.ExperimentBased, true, vBoolean());
export const InlineEditsXtabProviderPatchModelPredictionKind = defineTeamInternalSetting<xtabPromptOptions.PatchModelPrediction>('chat.advanced.inlineEdits.xtabProvider.patchModelPredictionKind', ConfigType.ExperimentBased, xtabPromptOptions.PatchModelPrediction.FilePath, xtabPromptOptions.PatchModelPrediction.VALIDATOR);
export const InlineEditsXtabProviderPatchFastYieldLineWithCursor = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.patchFastYieldLineWithCursor', ConfigType.ExperimentBased, true, vBoolean());
export const InlineEditsXtabProviderPatchModelPredictionKind = defineSetting<xtabPromptOptions.PatchModelPrediction>('chat.advanced.inlineEdits.xtabProvider.patchModelPredictionKind', ConfigType.ExperimentBased, xtabPromptOptions.PatchModelPrediction.FilePath, xtabPromptOptions.PatchModelPrediction.VALIDATOR);
export const InlineEditsXtabProviderPatchFastYieldLineWithCursor = defineSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.patchFastYieldLineWithCursor', ConfigType.ExperimentBased, true, vBoolean());
export const InlineEditsXtabProviderPatchFastYieldLineWithCursorMultiLine = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.patchFastYieldLineWithCursorMultiLine', ConfigType.ExperimentBased, false, vBoolean());
export const InlineEditsXtabLanguageContextEnabledLanguages = defineTeamInternalSetting<LanguageContextLanguages>('chat.advanced.inlineEdits.xtabProvider.languageContext.enabledLanguages', ConfigType.Simple, LANGUAGE_CONTEXT_ENABLED_LANGUAGES);
export const InlineEditsXtabLanguageContextTraitsPosition = defineTeamInternalSetting<'before' | 'after'>('chat.advanced.inlineEdits.xtabProvider.languageContext.traitsPosition', ConfigType.ExperimentBased, 'before');
@@ -849,15 +849,15 @@ export namespace ConfigKey {
export const InlineEditsAsyncCompletions = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.asyncCompletions', ConfigType.ExperimentBased, true);
export const InlineEditsDebounceUseCoreRequestTime = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.debounceUseCoreRequestTime', ConfigType.ExperimentBased, false);
export const InlineEditsYieldToCopilot = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.yieldToCopilot', ConfigType.ExperimentBased, false);
export const InlineEditsExcludedProviders = defineTeamInternalSetting<string | undefined>('chat.advanced.inlineEdits.excludedProviders', ConfigType.ExperimentBased, undefined);
export const InlineEditsExcludedProviders = defineSetting<string | undefined>('chat.advanced.inlineEdits.excludedProviders', ConfigType.ExperimentBased, undefined);
export const InlineEditsEnableGhCompletionsProvider = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.githubCompletionsProvider.enabled', ConfigType.ExperimentBased, false);
export const InlineEditsCompletionsUrl = defineTeamInternalSetting<string | undefined>('chat.advanced.inlineEdits.completionsProvider.url', ConfigType.ExperimentBased, undefined);
export const InlineEditsDebounce = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.debounce', ConfigType.ExperimentBased, 100);
export const InlineEditsDebounce = defineSetting<number>('chat.advanced.inlineEdits.debounce', ConfigType.ExperimentBased, 100);
export const InlineEditsCacheCursorDistanceCheck = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.cacheCursorDistanceCheck', ConfigType.ExperimentBased, false);
export const InlineEditsCacheDelay = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.cacheDelay', ConfigType.ExperimentBased, 200);
export const InlineEditsCacheDelay = defineSetting<number>('chat.advanced.inlineEdits.cacheDelay', ConfigType.ExperimentBased, 200);
export const InlineEditsSubsequentCacheDelay = defineTeamInternalSetting<number | undefined>('chat.advanced.inlineEdits.subsequentCacheDelay', ConfigType.ExperimentBased, 0);
export const InlineEditsSpeculativeRequestDelay = defineTeamInternalSetting<number | undefined>('chat.advanced.inlineEdits.speculativeRequestDelay', ConfigType.ExperimentBased, 0);
export const InlineEditsRebasedCacheDelay = defineTeamInternalSetting<number | undefined>('chat.advanced.inlineEdits.rebasedCacheDelay', ConfigType.ExperimentBased, 0);
export const InlineEditsRebasedCacheDelay = defineSetting<number | undefined>('chat.advanced.inlineEdits.rebasedCacheDelay', ConfigType.ExperimentBased, 0);
export const InlineEditsAbsorbSubsequenceTyping = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.absorbSubsequenceTyping', ConfigType.ExperimentBased, false);
export const InlineEditsReverseAgreement = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.reverseAgreement', ConfigType.ExperimentBased, true);
export const InlineEditsMaxImperfectAgreementLength = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.maxImperfectAgreementLength', ConfigType.ExperimentBased, 1, vNumber());
@@ -871,7 +871,7 @@ export namespace ConfigKey {
*/
export const InlineEditsReanchorContentOnIndentationMismatch = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.reanchorContentOnIndentationMismatch', ConfigType.ExperimentBased, false, vBoolean());
export const InlineEditsBackoffDebounceEnabled = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.backoffDebounceEnabled', ConfigType.ExperimentBased, true);
export const InlineEditsExtraDebounceEndOfLine = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.extraDebounceEndOfLine', ConfigType.ExperimentBased, 2000);
export const InlineEditsExtraDebounceEndOfLine = defineSetting<number>('chat.advanced.inlineEdits.extraDebounceEndOfLine', ConfigType.ExperimentBased, 2000);
export const InlineEditsSpeculativeRequests = defineTeamInternalSetting<SpeculativeRequestsEnablement>('chat.advanced.inlineEdits.speculativeRequests', ConfigType.ExperimentBased, SpeculativeRequestsEnablement.Off, SpeculativeRequestsEnablement.VALIDATOR);
export const InlineEditsSpeculativeRequestsCursorPlacement = defineTeamInternalSetting<SpeculativeRequestsCursorPlacement>('chat.advanced.inlineEdits.speculativeRequestsCursorPlacement', ConfigType.ExperimentBased, SpeculativeRequestsCursorPlacement.AfterEditApplied, SpeculativeRequestsCursorPlacement.VALIDATOR);
export const InlineEditsSpeculativeRequestsAutoExpandEditWindowLines = defineTeamInternalSetting<SpeculativeRequestsAutoExpandEditWindowLines>('chat.advanced.inlineEdits.speculativeRequestsAutoExpandEditWindowLines', ConfigType.ExperimentBased, SpeculativeRequestsAutoExpandEditWindowLines.Off, SpeculativeRequestsAutoExpandEditWindowLines.VALIDATOR);
@@ -879,7 +879,7 @@ export namespace ConfigKey {
export const InlineEditsDebounceOnSelectionChange = defineTeamInternalSetting<number | undefined>('chat.advanced.inlineEdits.debounceOnSelectionChange', ConfigType.ExperimentBased, undefined);
export const InlineEditsTriggerOnEditorChangeStrategy = defineTeamInternalSetting<triggerOptions.DocumentSwitchTriggerStrategy>('chat.advanced.inlineEdits.triggerOnEditorChangeStrategy', ConfigType.ExperimentBased, triggerOptions.DocumentSwitchTriggerStrategy.AfterAcceptance, triggerOptions.DocumentSwitchTriggerStrategy.VALIDATOR);
export const InlineEditsProviderId = defineTeamInternalSetting<string | undefined>('chat.advanced.inlineEdits.providerId', ConfigType.ExperimentBased, undefined);
export const InlineEditsUnification = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.unification', ConfigType.ExperimentBased, false);
export const InlineEditsUnification = defineSetting<boolean>('chat.advanced.inlineEdits.unification', ConfigType.ExperimentBased, false);
export const InlineEditsNextCursorPredictionModelName = defineTeamInternalSetting<string | undefined>('chat.advanced.inlineEdits.nextCursorPrediction.modelName', ConfigType.ExperimentBased, undefined);
export const InlineEditsNextCursorPredictionUseEndpointProvider = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.nextCursorPrediction.useEndpointProvider', ConfigType.Simple, false, vBoolean());
export const InlineEditsNextCursorPredictionMaxResponseTokens = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.nextCursorPrediction.maxResponseTokens', ConfigType.ExperimentBased, 40);
@@ -925,7 +925,7 @@ export namespace ConfigKey {
export const InlineEditsXtabMaxMergeConflictLines = defineTeamInternalSetting<number | undefined>('chat.advanced.inlineEdits.xtabProvider.maxMergeConflictLines', ConfigType.ExperimentBased, undefined);
export const InlineEditsXtabOnlyMergeConflictLines = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.onlyMergeConflictLines', ConfigType.ExperimentBased, false);
export const InlineEditsXtabDuplicateAdditionsMode = defineTeamInternalSetting<DuplicateAdditionsMode>('chat.advanced.inlineEdits.xtabProvider.diffPatch.duplicateAdditionsMode', ConfigType.ExperimentBased, DuplicateAdditionsMode.Off, DuplicateAdditionsMode.VALIDATOR);
export const InlineEditsXtabSplitPatchOnDiff = defineTeamInternalSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.diffPatch.splitOnDiff', ConfigType.ExperimentBased, false, vBoolean());
export const InlineEditsXtabSplitPatchOnDiff = defineSetting<boolean>('chat.advanced.inlineEdits.xtabProvider.diffPatch.splitOnDiff', ConfigType.ExperimentBased, false, vBoolean());
export const InlineEditsXtabAggressivenessLevel = defineTeamInternalSetting<xtabPromptOptions.AggressivenessLevel | undefined>('chat.advanced.inlineEdits.xtabProvider.aggressivenessLevel', ConfigType.ExperimentBased, xtabPromptOptions.AggressivenessLevel.Medium);
export const InlineEditsAggressivenessLowMinResponseTimeMs = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.aggressiveness.lowMinResponseTimeMs', ConfigType.ExperimentBased, 1500);
export const InlineEditsAggressivenessMediumMinResponseTimeMs = defineTeamInternalSetting<number>('chat.advanced.inlineEdits.aggressiveness.mediumMinResponseTimeMs', ConfigType.ExperimentBased, 700);
@@ -42,6 +42,7 @@ vi.mock('vscode', () => {
});
import { ICopilotTokenStore } from '../../../authentication/common/copilotTokenStore';
import { NullExperimentationService } from '../../../telemetry/common/nullExperimentationService';
import { ConfigKey } from '../../common/configurationService';
import { ConfigurationServiceImpl } from '../configurationServiceImpl';
@@ -73,3 +74,48 @@ describe('ConfigurationServiceImpl - migrated chat.advanced setting fallback', (
expect(value).toEqual(userValue);
});
});
describe('ConfigurationServiceImpl - externally configurable advanced settings', () => {
test('reads advanced inline edit settings for external users', () => {
mockConfigStore.user = {
[ConfigKey.TeamInternal.InlineEditsUnification.fullyQualifiedId]: true,
[ConfigKey.TeamInternal.InlineEditsExcludedProviders.fullyQualifiedId]: 'completions,github.copilot',
[ConfigKey.TeamInternal.InlineEditsXtabProviderPatchModelPredictionKind.fullyQualifiedId]: 'currentLineCompleted',
[ConfigKey.TeamInternal.InlineEditsXtabSplitPatchOnDiff.fullyQualifiedId]: true,
[ConfigKey.TeamInternal.InlineEditsXtabProviderPatchFastYieldLineWithCursor.fullyQualifiedId]: false,
[ConfigKey.TeamInternal.InlineEditsNesMimicGhostTextBehavior.fullyQualifiedId]: true,
[ConfigKey.TeamInternal.InlineEditsRebasedCacheDelay.fullyQualifiedId]: 100,
[ConfigKey.TeamInternal.InlineEditsExtraDebounceEndOfLine.fullyQualifiedId]: 0,
[ConfigKey.TeamInternal.InlineEditsDebounce.fullyQualifiedId]: 0,
[ConfigKey.TeamInternal.InlineEditsCacheDelay.fullyQualifiedId]: 0,
};
mockConfigStore.defaults = {};
const service = new ConfigurationServiceImpl(fakeTokenStore);
const experimentationService = new NullExperimentationService();
expect({
unification: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsUnification, experimentationService),
excludedProviders: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsExcludedProviders, experimentationService),
patchModelPredictionKind: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderPatchModelPredictionKind, experimentationService),
splitOnDiff: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsXtabSplitPatchOnDiff, experimentationService),
patchFastYieldLineWithCursor: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderPatchFastYieldLineWithCursor, experimentationService),
nesMimicGhostTextBehavior: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsNesMimicGhostTextBehavior, experimentationService),
rebasedCacheDelay: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsRebasedCacheDelay, experimentationService),
extraDebounceEndOfLine: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsExtraDebounceEndOfLine, experimentationService),
debounce: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsDebounce, experimentationService),
cacheDelay: service.getExperimentBasedConfig(ConfigKey.TeamInternal.InlineEditsCacheDelay, experimentationService),
}).toEqual({
unification: true,
excludedProviders: 'completions,github.copilot',
patchModelPredictionKind: 'currentLineCompleted',
splitOnDiff: true,
patchFastYieldLineWithCursor: false,
nesMimicGhostTextBehavior: true,
rebasedCacheDelay: 100,
extraDebounceEndOfLine: 0,
debounce: 0,
cacheDelay: 0,
});
});
});