diff --git a/extensions/copilot/src/extension/extension/vscode-node/services.ts b/extensions/copilot/src/extension/extension/vscode-node/services.ts index b4bb28dd53b..543eaf6283c 100644 --- a/extensions/copilot/src/extension/extension/vscode-node/services.ts +++ b/extensions/copilot/src/extension/extension/vscode-node/services.ts @@ -94,6 +94,7 @@ import { GitCommitMessageServiceImpl } from '../../prompt/vscode-node/gitCommitM import { GitDiffService } from '../../prompt/vscode-node/gitDiffService'; import { PromptVariablesServiceImpl } from '../../prompt/vscode-node/promptVariablesService'; import { RequestLogger } from '../../prompt/vscode-node/requestLoggerImpl'; +import { ScenarioAutomationEndpointProviderImpl } from '../../prompt/vscode-node/scenarioAutomationEndpointProviderImpl'; import { SettingsEditorSearchServiceImpl } from '../../prompt/vscode-node/settingsEditorSearchServiceImpl'; import { CodeMapperService, ICodeMapperService } from '../../prompts/node/codeMapper/codeMapperService'; import { FixCookbookService, IFixCookbookService } from '../../prompts/node/inline/fixCookbookService'; @@ -149,12 +150,14 @@ export function registerServices(builder: IInstantiationServiceBuilder, extensio if (isScenarioAutomation) { builder.define(IAuthenticationService, new SyncDescriptor(StaticGitHubAuthenticationService, [createStaticGitHubTokenProvider()])); + builder.define(IEndpointProvider, new SyncDescriptor(ScenarioAutomationEndpointProviderImpl, [collectFetcherTelemetry])); + } else { builder.define(IAuthenticationService, new SyncDescriptor(AuthenticationService)); + builder.define(IEndpointProvider, new SyncDescriptor(ProductionEndpointProvider, [collectFetcherTelemetry])); } builder.define(ITestGenInfoStorage, new SyncDescriptor(TestGenInfoStorage)); // Used for test generation (/tests intent) - builder.define(IEndpointProvider, new SyncDescriptor(ProductionEndpointProvider, [collectFetcherTelemetry])); builder.define(IParserService, new SyncDescriptor(ParserServiceImpl, [/*useWorker*/ true])); builder.define(IIntentService, new SyncDescriptor(IntentService)); builder.define(IIgnoreService, new SyncDescriptor(VsCodeIgnoreService)); diff --git a/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts b/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts index 49f9495ece7..4388020c7b9 100644 --- a/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts +++ b/extensions/copilot/src/extension/prompt/vscode-node/endpointProviderImpl.ts @@ -41,11 +41,11 @@ export class ProductionEndpointProvider implements IEndpointProvider { @IAutomodeService private readonly _autoModeService: IAutomodeService, @IExperimentationService private readonly _expService: IExperimentationService, @ITelemetryService private readonly _telemetryService: ITelemetryService, - @ILogService private readonly _logService: ILogService, + @ILogService protected readonly _logService: ILogService, @IConfigurationService private readonly _configService: IConfigurationService, - @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IInstantiationService protected readonly _instantiationService: IInstantiationService, @IEnvService _envService: IEnvService, - @IAuthenticationService _authService: IAuthenticationService, + @IAuthenticationService protected readonly _authService: IAuthenticationService, @IRequestLogger _requestLogger: IRequestLogger ) { diff --git a/extensions/copilot/src/extension/prompt/vscode-node/scenarioAutomationEndpointProviderImpl.ts b/extensions/copilot/src/extension/prompt/vscode-node/scenarioAutomationEndpointProviderImpl.ts new file mode 100644 index 00000000000..3f0fe53b542 --- /dev/null +++ b/extensions/copilot/src/extension/prompt/vscode-node/scenarioAutomationEndpointProviderImpl.ts @@ -0,0 +1,41 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ChatRequest, LanguageModelChat, lm } from 'vscode'; +import { ChatEndpointFamily } from '../../../platform/endpoint/common/endpointProvider'; +import { ExtensionContributedChatEndpoint } from '../../../platform/endpoint/vscode-node/extChatEndpoint'; +import { IChatEndpoint } from '../../../platform/networking/common/networking'; +import { ProductionEndpointProvider } from './endpointProviderImpl'; + +export class ScenarioAutomationEndpointProviderImpl extends ProductionEndpointProvider { + override async getChatEndpoint(requestOrFamilyOrModel: LanguageModelChat | ChatRequest | ChatEndpointFamily): Promise { + if (this._authService.copilotToken?.isNoAuthUser) { + // When using no auth in scenario automation, we want to force using a custom model / non-copilot for all requests + const getFirstNonCopilotModel = async () => { + const allModels = await lm.selectChatModels(); + const firstNonCopilotModel = allModels.find(m => m.vendor !== 'copilot'); + if (firstNonCopilotModel) { + this._logService.trace(`Using custom contributed chat model`); + return this._instantiationService.createInstance(ExtensionContributedChatEndpoint, firstNonCopilotModel); + } else { + throw new Error('No custom contributed chat models found.'); + } + }; + + // Check if we have a hard-coded family which indicates a copilot model + if (typeof requestOrFamilyOrModel === 'string') { + return getFirstNonCopilotModel(); + } + + // Check if a copilot model was explicitly requested in the picker + const model = 'model' in requestOrFamilyOrModel ? requestOrFamilyOrModel.model : requestOrFamilyOrModel; + if (model.vendor === 'copilot') { + return getFirstNonCopilotModel(); + } + } + + return super.getChatEndpoint(requestOrFamilyOrModel); + } +} \ No newline at end of file