@@ -12,12 +12,14 @@ import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposab
1212import { derived , IObservable , IObservableWithChange , ITransaction , observableValue , recordChangesLazy , transaction } from '../../../../../base/common/observable.js' ;
1313// eslint-disable-next-line local/code-no-deep-import-of-internal
1414import { observableReducerSettable } from '../../../../../base/common/observableInternal/experimental/reducer.js' ;
15- import { isDefined } from '../../../../../base/common/types.js' ;
15+ import { isDefined , isObject } from '../../../../../base/common/types.js' ;
1616import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js' ;
17+ import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js' ;
1718import { DataChannelForwardingTelemetryService , forwardToChannelIf , isCopilotLikeExtension } from '../../../../../platform/dataChannel/browser/forwardingTelemetryService.js' ;
1819import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js' ;
1920import { ILogService } from '../../../../../platform/log/common/log.js' ;
2021import { observableConfigValue } from '../../../../../platform/observable/common/platformObservableUtils.js' ;
22+ import product from '../../../../../platform/product/common/product.js' ;
2123import { StringEdit } from '../../../../common/core/edits/stringEdit.js' ;
2224import { Position } from '../../../../common/core/position.js' ;
2325import { InlineCompletionEndOfLifeReasonKind , InlineCompletionTriggerKind , InlineCompletionsProvider } from '../../../../common/languages.js' ;
@@ -73,6 +75,8 @@ export class InlineCompletionsSource extends Disposable {
7375 public readonly inlineCompletions = this . _state . map ( this , v => v . inlineCompletions ) ;
7476 public readonly suggestWidgetInlineCompletions = this . _state . map ( this , v => v . suggestWidgetInlineCompletions ) ;
7577
78+ private _completionsEnabled : Record < string , boolean > | undefined = undefined ;
79+
7680 constructor (
7781 private readonly _textModel : ITextModel ,
7882 private readonly _versionId : IObservableWithChange < number | null , IModelContentChangedEvent | undefined > ,
@@ -82,6 +86,7 @@ export class InlineCompletionsSource extends Disposable {
8286 @ILogService private readonly _logService : ILogService ,
8387 @IConfigurationService private readonly _configurationService : IConfigurationService ,
8488 @IInstantiationService private readonly _instantiationService : IInstantiationService ,
89+ @IContextKeyService private readonly _contextKeyService : IContextKeyService ,
8590 ) {
8691 super ( ) ;
8792 this . _loggingEnabled = observableConfigValue ( 'editor.inlineSuggest.logFetch' , false , this . _configurationService ) . recomputeInitiallyAndOnChange ( this . _store ) ;
@@ -94,6 +99,25 @@ export class InlineCompletionsSource extends Disposable {
9499 ) ) ;
95100
96101 this . clearOperationOnTextModelChange . recomputeInitiallyAndOnChange ( this . _store ) ;
102+
103+ const enablementSetting = product . defaultChatAgent ?. completionsEnablementSetting ?? undefined ;
104+ if ( enablementSetting ) {
105+ this . _updateCompletionsEnablement ( enablementSetting ) ;
106+ this . _register ( this . _configurationService . onDidChangeConfiguration ( e => {
107+ if ( e . affectsConfiguration ( enablementSetting ) ) {
108+ this . _updateCompletionsEnablement ( enablementSetting ) ;
109+ }
110+ } ) ) ;
111+ }
112+ }
113+
114+ private _updateCompletionsEnablement ( enalementSetting : string ) {
115+ const result = this . _configurationService . getValue < Record < string , boolean > > ( enalementSetting ) ;
116+ if ( ! isObject ( result ) ) {
117+ this . _completionsEnabled = undefined ;
118+ } else {
119+ this . _completionsEnabled = result ;
120+ }
97121 }
98122
99123 public readonly clearOperationOnTextModelChange = derived ( this , reader => {
@@ -260,7 +284,8 @@ export class InlineCompletionsSource extends Disposable {
260284 if ( source . token . isCancellationRequested ) {
261285 requestResponseInfo . setNoSuggestionReasonIfNotSet ( 'canceled:whileFetching' ) ;
262286 } else {
263- requestResponseInfo . setNoSuggestionReasonIfNotSet ( 'noSuggestion' ) ;
287+ const completionsQuotaExceeded = this . _contextKeyService . getContextKeyValue < boolean > ( 'completionsQuotaExceeded' ) ;
288+ requestResponseInfo . setNoSuggestionReasonIfNotSet ( completionsQuotaExceeded ? 'completionsQuotaExceeded' : 'noSuggestion' ) ;
264289 }
265290 }
266291
@@ -356,14 +381,23 @@ export class InlineCompletionsSource extends Disposable {
356381 private sendInlineCompletionsRequestTelemetry (
357382 requestResponseInfo : RequestResponseData
358383 ) : void {
359- if ( ! this . _sendRequestData . get ( ) ) {
384+ if ( ! this . _sendRequestData . get ( ) && ! this . _contextKeyService . getContextKeyValue < boolean > ( 'isRunningUnificationExperiment' ) ) {
360385 return ;
361386 }
362387
363388 if ( requestResponseInfo . requestUuid === undefined || requestResponseInfo . hasProducedSuggestion ) {
364389 return ;
365390 }
366391
392+
393+ if ( ! isCompletionsEnabled ( this . _completionsEnabled , this . _textModel . getLanguageId ( ) ) ) {
394+ return ;
395+ }
396+
397+ if ( ! requestResponseInfo . providers . some ( p => isCopilotLikeExtension ( p . providerId ?. extensionId ) ) ) {
398+ return ;
399+ }
400+
367401 const emptyEndOfLifeEvent : InlineCompletionEndOfLifeEvent = {
368402 id : requestResponseInfo . requestUuid ,
369403 opportunityId : requestResponseInfo . requestUuid ,
@@ -472,6 +506,18 @@ function isSubset<T>(set1: Set<T>, set2: Set<T>): boolean {
472506 return [ ...set1 ] . every ( item => set2 . has ( item ) ) ;
473507}
474508
509+ function isCompletionsEnabled ( completionsEnablementObject : Record < string , boolean > | undefined , modeId : string = '*' ) : boolean {
510+ if ( completionsEnablementObject === undefined ) {
511+ return false ; // default to disabled if setting is not available
512+ }
513+
514+ if ( typeof completionsEnablementObject [ modeId ] !== 'undefined' ) {
515+ return Boolean ( completionsEnablementObject [ modeId ] ) ; // go with setting if explicitly defined
516+ }
517+
518+ return Boolean ( completionsEnablementObject [ '*' ] ) ; // fallback to global setting otherwise
519+ }
520+
475521class UpdateOperation implements IDisposable {
476522 constructor (
477523 public readonly request : UpdateRequest ,
0 commit comments