Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3914,6 +3914,16 @@
"onExp"
]
},
"github.copilot.nextEditSuggestions.preferredModel": {
"type": "string",
"default": "none",
"markdownDescription": "%github.copilot.config.nextEditSuggestions.preferredModel%",
"tags": [
"advanced",
"experimental",
"onExp"
]
},
"github.copilot.chat.suggestRelatedFilesFromGitHistory.useEmbeddings": {
"type": "boolean",
"default": false,
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@
"github.copilot.config.inlineEdits.nextCursorPrediction.displayLine": "Display predicted cursor line for next edit suggestions.",
"github.copilot.config.inlineEdits.nextCursorPrediction.currentFileMaxTokens": "Maximum tokens for current file in next cursor prediction.",
"github.copilot.config.inlineEdits.renameSymbolSuggestions": "Enable rename symbol suggestions in inline edits.",
"github.copilot.config.nextEditSuggestions.preferredModel": "Preferred model for next edit suggestions.",
"github.copilot.command.refreshAgentSessions": "Refresh Agent Sessions",
"github.copilot.command.deleteAgentSession": "Delete Agent Session",
"github.copilot.command.cli.sessions.resumeInTerminal": "Resume Agent Session in Terminal",
Expand Down
3 changes: 3 additions & 0 deletions src/extension/extension/vscode-node/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { IIgnoreService, NullIgnoreService } from '../../../platform/ignore/comm
import { VsCodeIgnoreService } from '../../../platform/ignore/vscode-node/ignoreService';
import { IImageService } from '../../../platform/image/common/imageService';
import { ImageServiceImpl } from '../../../platform/image/node/imageServiceImpl';
import { IInlineEditsModelService } from '../../../platform/inlineEdits/common/inlineEditsModelService';
import { InlineEditsModelService } from '../../../platform/inlineEdits/node/inlineEditsModelService';
import { ILanguageContextProviderService } from '../../../platform/languageContextProvider/common/languageContextProviderService';
import { ILanguageContextService } from '../../../platform/languageServer/common/languageContextService';
import { ICompletionsFetchService } from '../../../platform/nesFetch/common/completionsFetchService';
Expand Down Expand Up @@ -204,6 +206,7 @@ export function registerServices(builder: IInstantiationServiceBuilder, extensio
builder.define(ITodoListContextProvider, new SyncDescriptor(TodoListContextProvider));
builder.define(IGithubAvailableEmbeddingTypesService, new SyncDescriptor(GithubAvailableEmbeddingTypesService));
builder.define(IRerankerService, new SyncDescriptor(RerankerService));
builder.define(IInlineEditsModelService, new SyncDescriptor(InlineEditsModelService));
}

function setupMSFTExperimentationService(builder: IInstantiationServiceBuilder, extensionContext: ExtensionContext) {
Expand Down
35 changes: 30 additions & 5 deletions src/extension/inlineEdits/vscode-node/inlineCompletionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import * as l10n from '@vscode/l10n';
import { CancellationToken, Command, EndOfLine, InlineCompletionContext, InlineCompletionDisplayLocation, InlineCompletionDisplayLocationKind, InlineCompletionEndOfLifeReason, InlineCompletionEndOfLifeReasonKind, InlineCompletionItem, InlineCompletionItemProvider, InlineCompletionList, InlineCompletionsDisposeReason, InlineCompletionsDisposeReasonKind, NotebookCell, NotebookCellKind, Position, Range, TextDocument, TextDocumentShowOptions, Event as vscodeEvent, window, workspace } from 'vscode';
import { CancellationToken, Command, EndOfLine, InlineCompletionContext, InlineCompletionDisplayLocation, InlineCompletionDisplayLocationKind, InlineCompletionEndOfLifeReason, InlineCompletionEndOfLifeReasonKind, InlineCompletionItem, InlineCompletionItemProvider, InlineCompletionList, InlineCompletionModelInfo, InlineCompletionsDisposeReason, InlineCompletionsDisposeReasonKind, NotebookCell, NotebookCellKind, Position, Range, TextDocument, TextDocumentShowOptions, Event as vscodeEvent, window, workspace } from 'vscode';
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
import { IDiffService } from '../../../platform/diff/common/diffService';
import { stringEditFromDiff } from '../../../platform/editing/common/edit';
Expand All @@ -13,6 +13,7 @@ import { EditSurvivalReporter } from '../../../platform/editSurvivalTracking/com
import { IGitExtensionService } from '../../../platform/git/common/gitExtensionService';
import { DocumentId } from '../../../platform/inlineEdits/common/dataTypes/documentId';
import { InlineEditRequestLogContext } from '../../../platform/inlineEdits/common/inlineEditLogContext';
import { IInlineEditsModelService } from '../../../platform/inlineEdits/common/inlineEditsModelService';
import { ShowNextEditPreference } from '../../../platform/inlineEdits/common/statelessNextEditProvider';
import { shortenOpportunityId } from '../../../platform/inlineEdits/common/utils/utils';
import { ILogService } from '../../../platform/log/common/logService';
Expand All @@ -24,11 +25,12 @@ import { IExperimentationService } from '../../../platform/telemetry/common/null
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';
import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService';
import { findCell, findNotebook, isNotebookCell } from '../../../util/common/notebooks';
import { ITracer, createTracer } from '../../../util/common/tracing';
import { createTracer, ITracer } from '../../../util/common/tracing';
import { raceCancellation, timeout } from '../../../util/vs/base/common/async';
import { CancellationTokenSource } from '../../../util/vs/base/common/cancellation';
import { Event } from '../../../util/vs/base/common/event';
import { IObservable } from '../../../util/vs/base/common/observable';
import { Emitter, Event } from '../../../util/vs/base/common/event';
import { Disposable } from '../../../util/vs/base/common/lifecycle';
import { autorun, IObservable, observableFromEvent } from '../../../util/vs/base/common/observable';
import { basename } from '../../../util/vs/base/common/path';
import { StringEdit } from '../../../util/vs/editor/common/core/edits/stringEdit';
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
Expand Down Expand Up @@ -101,7 +103,7 @@ function isLlmCompletionInfo(item: NesCompletionInfo): item is LlmCompletionInfo
const GoToNextEdit = l10n.t('Go To Inline Suggestion');


export class InlineCompletionProviderImpl implements InlineCompletionItemProvider {
export class InlineCompletionProviderImpl extends Disposable implements InlineCompletionItemProvider {
public readonly displayName = 'Inline Suggestion';

private readonly _tracer: ITracer;
Expand All @@ -110,6 +112,17 @@ export class InlineCompletionProviderImpl implements InlineCompletionItemProvide
public readonly handleDidPartiallyAcceptCompletionItem = undefined;
public readonly handleDidRejectCompletionItem = undefined;

//#region Model picker
private _isModelPickerEnabled: IObservable<boolean> = this._configurationService.getExperimentBasedConfigObservable(ConfigKey.TeamInternal.InlineEditsModelPickerEnabled, this._expService);

public modelInfo: InlineCompletionModelInfo | undefined;

private readonly _onDidChangeModelInfo = this._register(new Emitter<void>());
public onDidChangeModelInfo = this._onDidChangeModelInfo.event;

public setCurrentModelId: ((modelId: string) => Thenable<void>) | undefined;
//#endregion

private readonly _displayNextEditorNES: boolean;
private readonly _renameSymbolSuggestions: IObservable<boolean>;

Expand All @@ -129,10 +142,22 @@ export class InlineCompletionProviderImpl implements InlineCompletionItemProvide
@INotebookService private readonly _notebookService: INotebookService,
@IWorkspaceService private readonly _workspaceService: IWorkspaceService,
@IRequestLogger private readonly _requestLogger: IRequestLogger,
@IInlineEditsModelService private readonly _modelService: IInlineEditsModelService,
) {
super();
this._tracer = createTracer(['NES', 'Provider'], (s) => this._logService.trace(s));
this._displayNextEditorNES = this._configurationService.getExperimentBasedConfig(ConfigKey.Advanced.UseAlternativeNESNotebookFormat, this._expService);
this._renameSymbolSuggestions = this._configurationService.getExperimentBasedConfigObservable(ConfigKey.Advanced.InlineEditsRenameSymbolSuggestions, this._expService);

this.setCurrentModelId = (modelId: string) => this._modelService.setCurrentModelId(modelId);

const modelListUpdatedObs = observableFromEvent(this, this._modelService.onModelListUpdated, () => this._modelService.modelInfo);

this._register(autorun(reader => {
this.modelInfo = this._isModelPickerEnabled.read(reader) ? modelListUpdatedObs.read(reader) : undefined;
this._onDidChangeModelInfo.fire();
}));

}

// copied from `vscodeWorkspace.ts` `DocumentFilter#_enabledLanguages`
Expand Down
3 changes: 3 additions & 0 deletions src/extension/test/node/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { IGitExtensionService } from '../../../platform/git/common/gitExtensionS
import { IGitService } from '../../../platform/git/common/gitService';
import { NullGitDiffService } from '../../../platform/git/common/nullGitDiffService';
import { NullGitExtensionService } from '../../../platform/git/common/nullGitExtensionService';
import { IInlineEditsModelService } from '../../../platform/inlineEdits/common/inlineEditsModelService';
import { InlineEditsModelService } from '../../../platform/inlineEdits/node/inlineEditsModelService';
import { ILogService } from '../../../platform/log/common/logService';
import { EditLogService, IEditLogService } from '../../../platform/multiFileEdit/common/editLogService';
import { IMultiFileEditInternalTelemetryService, MultiFileEditInternalTelemetryService } from '../../../platform/multiFileEdit/common/multiFileEditQualityTelemetry';
Expand Down Expand Up @@ -94,6 +96,7 @@ export function createExtensionUnitTestingServices(disposables: Pick<DisposableS
testingServiceCollection.define(IToolsService, new SyncDescriptor(TestToolsService, [new Set()]));
testingServiceCollection.define(IClaudeCodeSdkService, new SyncDescriptor(MockClaudeCodeSdkService));
testingServiceCollection.define(IEditLogService, new SyncDescriptor(EditLogService));
testingServiceCollection.define(IInlineEditsModelService, new SyncDescriptor(InlineEditsModelService));
testingServiceCollection.define(IMultiFileEditInternalTelemetryService, new SyncDescriptor(MultiFileEditInternalTelemetryService));
testingServiceCollection.define(ICodeMapperService, new SyncDescriptor(CodeMapperService));
testingServiceCollection.define(IAlternativeNotebookContentService, new SyncDescriptor(SimulationAlternativeNotebookContentService));
Expand Down
3 changes: 3 additions & 0 deletions src/extension/test/vscode-node/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import { IOctoKitService } from '../../../platform/github/common/githubService';
import { OctoKitService } from '../../../platform/github/common/octoKitServiceImpl';
import { IIgnoreService, NullIgnoreService } from '../../../platform/ignore/common/ignoreService';
import { IImageService, nullImageService } from '../../../platform/image/common/imageService';
import { IInlineEditsModelService } from '../../../platform/inlineEdits/common/inlineEditsModelService';
import { InlineEditsModelService } from '../../../platform/inlineEdits/node/inlineEditsModelService';
import { ILanguageDiagnosticsService } from '../../../platform/languages/common/languageDiagnosticsService';
import { ILanguageFeaturesService, NoopLanguageFeaturesService } from '../../../platform/languages/common/languageFeaturesService';
import { LanguageDiagnosticsServiceImpl } from '../../../platform/languages/vscode/languageDiagnosticsServiceImpl';
Expand Down Expand Up @@ -187,6 +189,7 @@ export function createExtensionTestingServices(): TestingServiceCollection {
testingServiceCollection.define(IToolGroupingService, new SyncDescriptor(ToolGroupingService));
testingServiceCollection.define(ITodoListContextProvider, new SyncDescriptor(TodoListContextProvider));
testingServiceCollection.define(IGithubAvailableEmbeddingTypesService, new SyncDescriptor(GithubAvailableEmbeddingTypesService));
testingServiceCollection.define(IInlineEditsModelService, new SyncDescriptor(InlineEditsModelService));

return testingServiceCollection;
}
Expand Down
53 changes: 5 additions & 48 deletions src/extension/xtab/node/xtabProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { Raw } from '@vscode/prompt-tsx';
import { FetchStreamSource } from '../../../platform/chat/common/chatMLFetcher';
import { ChatFetchError, ChatFetchResponseType, ChatLocation } from '../../../platform/chat/common/commonTypes';
import { ConfigKey, ExperimentBasedConfig, IConfigurationService, XTabProviderId } from '../../../platform/configuration/common/configurationService';
import { ConfigKey, IConfigurationService, XTabProviderId } from '../../../platform/configuration/common/configurationService';
import { IDiffService } from '../../../platform/diff/common/diffService';
import { ChatEndpoint } from '../../../platform/endpoint/node/chatEndpoint';
import { createProxyXtabEndpoint } from '../../../platform/endpoint/node/proxyXtabEndpoint';
Expand All @@ -18,6 +18,7 @@ import { NextCursorLinePrediction } from '../../../platform/inlineEdits/common/d
import * as xtabPromptOptions from '../../../platform/inlineEdits/common/dataTypes/xtabPromptOptions';
import { LanguageContextLanguages, LanguageContextOptions } from '../../../platform/inlineEdits/common/dataTypes/xtabPromptOptions';
import { InlineEditRequestLogContext } from '../../../platform/inlineEdits/common/inlineEditLogContext';
import { IInlineEditsModelService } from '../../../platform/inlineEdits/common/inlineEditsModelService';
import { ResponseProcessor } from '../../../platform/inlineEdits/common/responseProcessor';
import { IStatelessNextEditProvider, NoNextEditReason, PushEdit, ShowNextEditPreference, StatelessNextEditDocument, StatelessNextEditRequest, StatelessNextEditResult, StatelessNextEditTelemetryBuilder } from '../../../platform/inlineEdits/common/statelessNextEditProvider';
import { editWouldDeleteWhatWasJustInserted, editWouldDeleteWhatWasJustInserted2, IgnoreEmptyLineAndLeadingTrailingWhitespaceChanges, IgnoreWhitespaceOnlyChanges } from '../../../platform/inlineEdits/common/statelessNextEditProviders';
Expand All @@ -28,7 +29,6 @@ import { OptionalChatRequestParams, Prediction } from '../../../platform/network
import { IChatEndpoint } from '../../../platform/networking/common/networking';
import { ISimulationTestContext } from '../../../platform/simulationTestContext/common/simulationTestContext';
import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';
import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';
import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService';
import { raceFilter } from '../../../util/common/async';
import * as errors from '../../../util/common/errors';
Expand Down Expand Up @@ -83,6 +83,7 @@ export class XtabProvider implements IStatelessNextEditProvider {
private nextCursorPredictor: XtabNextCursorPredictor;

constructor(
@IInlineEditsModelService private readonly modelService: IInlineEditsModelService,
@ISimulationTestContext private readonly simulationCtx: ISimulationTestContext,
@IInstantiationService private readonly instaService: IInstantiationService,
@IWorkspaceService private readonly workspaceService: IWorkspaceService,
Expand All @@ -92,7 +93,6 @@ export class XtabProvider implements IStatelessNextEditProvider {
@ILanguageContextProviderService private readonly langCtxService: ILanguageContextProviderService,
@ILanguageDiagnosticsService private readonly langDiagService: ILanguageDiagnosticsService,
@IIgnoreService private readonly ignoreService: IIgnoreService,
@ITelemetryService private readonly telemetryService: ITelemetryService
) {
this.delayer = new Delayer(this.configService, this.expService);
this.nextCursorPredictor = this.instaService.createInstance(XtabNextCursorPredictor, XtabProvider.computeTokens);
Expand Down Expand Up @@ -1009,51 +1009,8 @@ export class XtabProvider implements IStatelessNextEditProvider {
includePostScript: true,
};

const localOverridingModelConfig = this.configService.getConfig(ConfigKey.TeamInternal.InlineEditsXtabProviderModelConfiguration);
if (localOverridingModelConfig) {
return XtabProvider.overrideModelConfig(sourcedModelConfig, localOverridingModelConfig);
}

const expBasedModelConfig = this.overrideByStringModelConfig(sourcedModelConfig, ConfigKey.TeamInternal.InlineEditsXtabProviderModelConfigurationString);
if (expBasedModelConfig) {
return expBasedModelConfig;
}

const defaultModelConfig = this.overrideByStringModelConfig(sourcedModelConfig, ConfigKey.TeamInternal.InlineEditsXtabProviderDefaultModelConfigurationString);
if (defaultModelConfig) {
return defaultModelConfig;
}

return sourcedModelConfig;
}

private overrideByStringModelConfig(originalModelConfig: ModelConfig, configKey: ExperimentBasedConfig<string | undefined>): ModelConfig | undefined {
const configString = this.configService.getExperimentBasedConfig(configKey, this.expService);
if (configString === undefined) {
return undefined;
}

let parsedConfig: xtabPromptOptions.ModelConfiguration | undefined;
try {
parsedConfig = JSON.parse(configString);
} catch (e: unknown) {
/* __GDPR__
"incorrectNesModelConfig" : {
"owner": "ulugbekna",
"comment": "Capture if model configuration string is invalid JSON.",
"configName": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Name of the configuration that failed to parse." },
"errorMessage": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Error message from JSON.parse." },
"configValue": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The invalid JSON string." }
}
*/
this.telemetryService.sendMSFTTelemetryEvent('incorrectNesModelConfig', { configName: configKey.id, errorMessage: errors.toString(errors.fromUnknown(e)), configValue: configString });
}

if (parsedConfig) {
return XtabProvider.overrideModelConfig(originalModelConfig, parsedConfig);
}

return undefined;
const modelConfig = this.modelService.selectedModelConfiguration();
return XtabProvider.overrideModelConfig(sourcedModelConfig, modelConfig);
}

private static overrideModelConfig(modelConfig: ModelConfig, overridingConfig: xtabPromptOptions.ModelConfiguration): ModelConfig {
Expand Down
Loading
Loading