44 *--------------------------------------------------------------------------------------------*/
55
66import { Emitter , Event } from '../../../../../../base/common/event.js' ;
7- import { Disposable , IReference , toDisposable } from '../../../../../../base/common/lifecycle.js' ;
7+ import { Disposable , DisposableStore , IDisposable , IReference , toDisposable } from '../../../../../../base/common/lifecycle.js' ;
88import { URI , UriComponents } from '../../../../../../base/common/uri.js' ;
99import { Registry } from '../../../../../../platform/registry/common/platform.js' ;
1010import { IAgentConnection , IAgentCreateSessionConfig , IAgentResolveSessionConfigParams , IAgentSessionConfigCompletionsParams , IAgentSessionMetadata , IAuthenticateParams , IAuthenticateResult , AgentHostIpcLoggingSettingId } from '../../../../../../platform/agentHost/common/agentService.js' ;
@@ -98,6 +98,12 @@ export class LoggingAgentConnection extends Disposable implements IAgentConnecti
9898 /** Ref-count per channel ID so the output channel survives reconnections. */
9999 private static readonly _channelRefCounts = new Map < string , number > ( ) ;
100100 private static readonly _currentRootStateLogKeys = new Set < string > ( ) ;
101+ /**
102+ * Shared event-log subscription per channel ID. Multiple wrappers may
103+ * exist for the same underlying connection (e.g. one for chat, one for
104+ * terminal); we only want each event to appear once in the channel.
105+ */
106+ private static readonly _sharedEventLog = new Map < string , IDisposable > ( ) ;
101107
102108 private _outputChannel : IOutputChannel | undefined ;
103109 private readonly _enabled : boolean ;
@@ -130,6 +136,10 @@ export class LoggingAgentConnection extends Disposable implements IAgentConnecti
130136 log : false ,
131137 languageId : 'log' ,
132138 } ) ;
139+ const eventLogStore = new DisposableStore ( ) ;
140+ eventLogStore . add ( _inner . onDidAction ( e => this . _log ( '**' , 'onDidAction' , e ) ) ) ;
141+ eventLogStore . add ( _inner . onDidNotification ( e => this . _log ( '**' , 'onDidNotification' , e ) ) ) ;
142+ LoggingAgentConnection . _sharedEventLog . set ( this . channelId , eventLogStore ) ;
133143 }
134144 LoggingAgentConnection . _channelRefCounts . set ( this . channelId , refs + 1 ) ;
135145 logCurrentRootState = ! LoggingAgentConnection . _currentRootStateLogKeys . has ( currentRootStateLogKey ) ;
@@ -141,27 +151,21 @@ export class LoggingAgentConnection extends Disposable implements IAgentConnecti
141151 if ( current <= 0 ) {
142152 LoggingAgentConnection . _channelRefCounts . delete ( this . channelId ) ;
143153 LoggingAgentConnection . _currentRootStateLogKeys . delete ( currentRootStateLogKey ) ;
154+ LoggingAgentConnection . _sharedEventLog . get ( this . channelId ) ?. dispose ( ) ;
155+ LoggingAgentConnection . _sharedEventLog . delete ( this . channelId ) ;
144156 registry . removeChannel ( this . channelId ) ;
145157 } else {
146158 LoggingAgentConnection . _channelRefCounts . set ( this . channelId , current ) ;
147159 }
148160 } ) ) ;
149161 }
150162
151- // Wrap events with logging
152- const onDidActionEmitter = this . _register ( new Emitter < IActionEnvelope > ( ) ) ;
153- this . _register ( _inner . onDidAction ( e => {
154- this . _log ( '**' , 'onDidAction' , e ) ;
155- onDidActionEmitter . fire ( e ) ;
156- } ) ) ;
157- this . onDidAction = onDidActionEmitter . event ;
158-
159- const onDidNotificationEmitter = this . _register ( new Emitter < INotification > ( ) ) ;
160- this . _register ( _inner . onDidNotification ( e => {
161- this . _log ( '**' , 'onDidNotification' , e ) ;
162- onDidNotificationEmitter . fire ( e ) ;
163- } ) ) ;
164- this . onDidNotification = onDidNotificationEmitter . event ;
163+ // Expose the inner events directly. Logging happens once per channel
164+ // via the shared subscription registered above; wrappers must not
165+ // add their own logging listener or events would be logged N times
166+ // (once per wrapper for the same channel).
167+ this . onDidAction = _inner . onDidAction ;
168+ this . onDidNotification = _inner . onDidNotification ;
165169
166170 this . _rootState = this . _register ( new LoggingAgentSubscription ( 'rootState' , _inner . rootState , logCurrentRootState , ( arrow , method , data ) => this . _log ( arrow , method , data ) ) ) ;
167171 }
0 commit comments