@@ -5,6 +5,8 @@ import { primaryAIProviders } from '../../constants.ai';
55import type { AIGenerateDraftEventData , Source , TelemetryEvents } from '../../constants.telemetry' ;
66import type { Container } from '../../container' ;
77import { CancellationError } from '../../errors' ;
8+ import type { AIFeatures } from '../../features' ;
9+ import { isAdvancedFeature } from '../../features' ;
810import type { GitCommit } from '../../git/models/commit' ;
911import { isCommit } from '../../git/models/commit' ;
1012import type { GitRevisionReference } from '../../git/models/reference' ;
@@ -13,6 +15,7 @@ import { uncommitted, uncommittedStaged } from '../../git/models/revision';
1315import { assertsCommitHasFullDetails } from '../../git/utils/commit.utils' ;
1416import { showAIModelPicker } from '../../quickpicks/aiModelPicker' ;
1517import { configuration } from '../../system/-webview/configuration' ;
18+ import { getContext } from '../../system/-webview/context' ;
1619import type { Storage } from '../../system/-webview/storage' ;
1720import { supportedInVSCodeVersion } from '../../system/-webview/vscode' ;
1821import { debounce } from '../../system/function/debounce' ;
@@ -22,6 +25,7 @@ import { lazy } from '../../system/lazy';
2225import type { Deferred } from '../../system/promise' ;
2326import { getSettledValue } from '../../system/promise' ;
2427import type { ServerConnection } from '../gk/serverConnection' ;
28+ import { ensureFeatureAccess } from '../gk/utils/-webview/acount.utils' ;
2529import type { AIActionType , AIModel , AIModelDescriptor } from './models/model' ;
2630import type { PromptTemplateContext } from './models/promptTemplates' ;
2731import type { AIProvider , AIRequestResult } from './models/provider' ;
@@ -284,11 +288,44 @@ export class AIProviderService implements Disposable {
284288 return model ;
285289 }
286290
291+ private async ensureOrgAccess ( ) : Promise < boolean > {
292+ const orgEnabled = getContext ( 'gitlens:gk:organization:ai:enabled' ) ;
293+ if ( orgEnabled === false ) {
294+ await window . showErrorMessage ( `AI features have been disabled for your organization.` ) ;
295+ return false ;
296+ }
297+
298+ return true ;
299+ }
300+
301+ private async ensureFeatureAccess ( feature : AIFeatures , source : Source ) : Promise < boolean > {
302+ if ( ! ( await this . ensureOrgAccess ( ) ) ) return false ;
303+
304+ if (
305+ ! ( await ensureFeatureAccess (
306+ this . container ,
307+ isAdvancedFeature ( feature )
308+ ? `Advanced AI features require a trial or GitLens Advanced.`
309+ : `Pro AI features require a trial or GitLens Pro.` ,
310+ feature ,
311+ source ,
312+ ) )
313+ ) {
314+ return false ;
315+ }
316+
317+ return true ;
318+ }
319+
287320 async explainCommit (
288321 commitOrRevision : GitRevisionReference | GitCommit ,
289322 sourceContext : Source & { type : TelemetryEvents [ 'ai/explain' ] [ 'changeType' ] } ,
290323 options ?: { cancellation ?: CancellationToken ; progress ?: ProgressOptions } ,
291324 ) : Promise < AISummarizeResult | undefined > {
325+ if ( ! ( await this . ensureFeatureAccess ( 'explainCommit' , sourceContext ) ) ) {
326+ return undefined ;
327+ }
328+
292329 const diff = await this . container . git . diff ( commitOrRevision . repoPath ) . getDiff ?.( commitOrRevision . ref ) ;
293330 if ( ! diff ?. contents ) throw new Error ( 'No changes found to explain.' ) ;
294331
@@ -339,6 +376,8 @@ export class AIProviderService implements Disposable {
339376 progress ?: ProgressOptions ;
340377 } ,
341378 ) : Promise < AISummarizeResult | undefined > {
379+ if ( ! ( await this . ensureOrgAccess ( ) ) ) return undefined ;
380+
342381 const changes : string | undefined = await this . getChanges ( changesOrRepo ) ;
343382 if ( changes == null ) return undefined ;
344383
@@ -377,6 +416,10 @@ export class AIProviderService implements Disposable {
377416 codeSuggestion ?: boolean ;
378417 } ,
379418 ) : Promise < AISummarizeResult | undefined > {
419+ if ( ! ( await this . ensureFeatureAccess ( 'cloudPatchGenerateTitleAndDescription' , sourceContext ) ) ) {
420+ return undefined ;
421+ }
422+
380423 const changes : string | undefined = await this . getChanges ( changesOrRepo ) ;
381424 if ( changes == null ) return undefined ;
382425
@@ -423,6 +466,10 @@ export class AIProviderService implements Disposable {
423466 progress ?: ProgressOptions ;
424467 } ,
425468 ) : Promise < AISummarizeResult | undefined > {
469+ if ( ! ( await this . ensureFeatureAccess ( 'generateStashMessage' , source ) ) ) {
470+ return undefined ;
471+ }
472+
426473 const changes : string | undefined = await this . getChanges ( changesOrRepo ) ;
427474 if ( changes == null ) {
428475 options ?. generating ?. cancel ( ) ;
@@ -458,6 +505,10 @@ export class AIProviderService implements Disposable {
458505 source : Source ,
459506 options ?: { cancellation ?: CancellationToken ; progress ?: ProgressOptions } ,
460507 ) : Promise < AIResult | undefined > {
508+ if ( ! ( await this . ensureFeatureAccess ( 'generateChangelog' , source ) ) ) {
509+ return undefined ;
510+ }
511+
461512 const result = await this . sendRequest (
462513 'generate-changelog' ,
463514 async ( ) => ( {
0 commit comments