@@ -7,7 +7,7 @@ import { CopilotClient, ResumeSessionConfig, type CopilotClientOptions, type Ses
77import { rgPath } from '@vscode/ripgrep' ;
88import * as fs from 'fs/promises' ;
99import { Limiter , SequencerByKey } from '../../../../base/common/async.js' ;
10- import { Emitter } from '../../../../base/common/event.js' ;
10+ import { Emitter , Event } from '../../../../base/common/event.js' ;
1111import { appendEscapedMarkdownInlineCode } from '../../../../base/common/htmlContent.js' ;
1212import { Disposable , DisposableMap } from '../../../../base/common/lifecycle.js' ;
1313import { ResourceMap } from '../../../../base/common/map.js' ;
@@ -22,7 +22,7 @@ import { IParsedPlugin, parsePlugin } from '../../../agentPlugins/common/pluginP
2222import { IFileService } from '../../../files/common/files.js' ;
2323import { IInstantiationService } from '../../../instantiation/common/instantiation.js' ;
2424import { ILogService } from '../../../log/common/log.js' ;
25- import { customizationMatchesDirectory } from '../../common/agentHostCustomizationConfig.js' ;
25+ import { customizationMatchesDirectory , AgentHostConfigKey , agentHostCustomizationConfigSchema } from '../../common/agentHostCustomizationConfig.js' ;
2626import { IAgentPluginManager , ISyncedCustomization } from '../../common/agentPluginManager.js' ;
2727import { AgentSession , IAgent , IAgentAttachment , IAgentCreateSessionConfig , IAgentCreateSessionResult , IAgentDescriptor , IAgentDeltaEvent , IAgentMessageEvent , IAgentModelInfo , IAgentProgressEvent , IAgentResolveSessionConfigParams , IAgentSessionConfigCompletionsParams , IAgentSessionMetadata , IAgentSessionProjectInfo , IAgentSubagentStartedEvent , IAgentToolCompleteEvent , IAgentToolStartEvent } from '../../common/agentService.js' ;
2828import { AutoApproveLevel , ISchemaProperty , createSchema , platformSessionSchema , schemaProperty } from '../../common/agentHostSchema.js' ;
@@ -33,6 +33,7 @@ import { ProtectedResourceMetadata, SessionCustomizationSource, type ConfigSchem
3333import { AHP_AUTH_REQUIRED , ProtocolError } from '../../common/state/sessionProtocol.js' ;
3434import { CustomizationStatus , CustomizationRef , SessionInputResponseKind , type PendingMessage , type SessionInputAnswer , type ToolCallResult , type PolicyState } from '../../common/state/sessionState.js' ;
3535import { IAgentHostGitService } from '../agentHostGitService.js' ;
36+ import { IAgentConfigurationService } from '../agentConfigurationService.js' ;
3637import { IAgentHostTerminalManager } from '../agentHostTerminalManager.js' ;
3738import { CopilotAgentSession , SessionWrapperFactory , type IActiveClientSnapshot } from './copilotAgentSession.js' ;
3839import { ICopilotSessionContext , projectFromCopilotContext } from './copilotGitProject.js' ;
@@ -179,6 +180,7 @@ export class CopilotAgent extends Disposable implements IAgent {
179180 private readonly _sessionSequencer = new SequencerByKey < string > ( ) ;
180181 private _shutdownPromise : Promise < void > | undefined ;
181182 private readonly _plugins : PluginController ;
183+ readonly onDidCustomizationsChange : Event < void > ;
182184 /** Per-session active client state for tools + plugin snapshot tracking. */
183185 private readonly _activeClients = new ResourceMap < ActiveClient > ( ) ;
184186
@@ -191,7 +193,8 @@ export class CopilotAgent extends Disposable implements IAgent {
191193 @IAgentHostTerminalManager private readonly _terminalManager : IAgentHostTerminalManager ,
192194 ) {
193195 super ( ) ;
194- this . _plugins = this . _instantiationService . createInstance ( PluginController ) ;
196+ this . _plugins = this . _register ( this . _instantiationService . createInstance ( PluginController ) ) ;
197+ this . onDidCustomizationsChange = this . _plugins . onDidChange ;
195198 }
196199
197200 protected _createCopilotClient ( options : CopilotClientOptions ) : ICopilotClient {
@@ -228,10 +231,6 @@ export class CopilotAgent extends Disposable implements IAgent {
228231 return this . _plugins . getSessionCustomizations ( entry ?. customizationDirectory ?? metadata ?. customizationDirectory ?? metadata ?. workingDirectory ) ;
229232 }
230233
231- setHostCustomizations ( customizations : CustomizationRef [ ] , progress ?: ( ) => void ) : void {
232- this . _plugins . setHostCustomizations ( customizations , progress ) ;
233- }
234-
235234 async authenticate ( resource : string , token : string ) : Promise < boolean > {
236235 if ( resource !== 'https://api.github.com' ) {
237236 return false ;
@@ -1216,20 +1215,33 @@ interface IResolvedCustomization {
12161215 readonly plugin ?: IParsedPlugin ;
12171216}
12181217
1219- class PluginController {
1218+ class PluginController extends Disposable {
1219+ private readonly _onDidChange = this . _register ( new Emitter < void > ( ) ) ;
1220+ readonly onDidChange = this . _onDidChange . event ;
1221+
12201222 private readonly _enablement = new Map < string , boolean > ( ) ;
12211223 private _clientCustomizations : readonly IResolvedCustomization [ ] = [ ] ;
12221224 private _hostCustomizations : readonly IResolvedCustomization [ ] = [ ] ;
12231225 private _clientSync : Promise < readonly IResolvedCustomization [ ] > = Promise . resolve ( [ ] ) ;
12241226 private _hostSync : Promise < readonly IResolvedCustomization [ ] > = Promise . resolve ( [ ] ) ;
12251227 private _clientRevision = 0 ;
12261228 private _hostRevision = 0 ;
1229+ private _lastAppliedRefs : readonly CustomizationRef [ ] = [ ] ;
12271230
12281231 constructor (
12291232 @IAgentPluginManager private readonly _pluginManager : IAgentPluginManager ,
12301233 @ILogService private readonly _logService : ILogService ,
12311234 @IFileService private readonly _fileService : IFileService ,
1232- ) { }
1235+ @IAgentConfigurationService private readonly _configurationService : IAgentConfigurationService ,
1236+ ) {
1237+ super ( ) ;
1238+
1239+ // Seed from current root config and subscribe to future changes.
1240+ this . _applyHostCustomizations ( ) ;
1241+ this . _register ( this . _configurationService . onDidRootConfigChange ( ( ) => {
1242+ this . _applyHostCustomizations ( ) ;
1243+ } ) ) ;
1244+ }
12331245
12341246 public getConfiguredHostCustomizations ( ) : readonly CustomizationRef [ ] {
12351247 return this . _hostCustomizations . map ( item => item . customization . customization ) ;
@@ -1276,7 +1288,18 @@ class PluginController {
12761288 this . _enablement . set ( pluginProtocolUri , enabled ) ;
12771289 }
12781290
1279- public setHostCustomizations ( customizations : CustomizationRef [ ] , progress ?: ( ) => void ) : void {
1291+ /**
1292+ * Reads the current host customizations from the root config and
1293+ * resolves them. Skips the update when the configured refs have not
1294+ * changed since the last application.
1295+ */
1296+ private _applyHostCustomizations ( ) : void {
1297+ const customizations = this . _configurationService . getRootValue ( agentHostCustomizationConfigSchema , AgentHostConfigKey . Customizations ) ?? [ ] ;
1298+ if ( equals ( customizations , this . _lastAppliedRefs ) ) {
1299+ return ;
1300+ }
1301+ this . _lastAppliedRefs = customizations ;
1302+
12801303 const revision = ++ this . _hostRevision ;
12811304 this . _hostCustomizations = customizations . map ( customization => ( {
12821305 customization : {
@@ -1286,15 +1309,15 @@ class PluginController {
12861309 status : CustomizationStatus . Loading ,
12871310 } ,
12881311 } ) ) ;
1289- progress ?. ( ) ;
1312+ this . _onDidChange . fire ( ) ;
12901313 this . _hostSync = Promise . all ( customizations . map ( customization => this . _resolveConfiguredCustomization ( customization , SessionCustomizationSource . Host ) ) ) . then ( resolved => {
12911314 if ( revision === this . _hostRevision ) {
12921315 this . _hostCustomizations = resolved ;
12931316 }
12941317 return resolved ;
12951318 } ) . finally ( ( ) => {
12961319 if ( revision === this . _hostRevision ) {
1297- progress ?. ( ) ;
1320+ this . _onDidChange . fire ( ) ;
12981321 }
12991322 } ) ;
13001323 }
0 commit comments