agentHost: Attribute telemetry to initiating window#327417
Draft
roblourens wants to merge 1 commit into
Draft
Conversation
Identify editor and Agents window AHP clients and propagate the initiating client type onto existing Agent Host and Copilot CTS telemetry. Preserve attribution for queued turns and reconnect with a fresh initialize when the host no longer remembers the client.\n\n(Written by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds per-interaction “initiating window” attribution by propagating client identity (clientInfo) through Agent Host protocol initialization/reconnect and decorating existing telemetry with initiatorClientType.
Changes:
- Introduces
agentHostClientInfoutilities and threadsclientInfothrough local/remote/tunnel/WSL/SSH protocol clients and sessions. - Persists
clientInfoon the protocol server across reconnects, derivesAgentHostClientType, and forwards it through action dispatch + queued-message consumption. - Extends Agent Host + CTS/GitHub telemetry routing to include
initiatorClientType, plus reconnect fallback to re-initializewhen the server forgets the client.
Show a summary per file
| File | Description |
|---|---|
| src/vs/workbench/services/agentHost/test/browser/editorRemoteAgentHostServiceClient.test.ts | Asserts RemoteAgentHostProtocolClient is created with editor-window client info. |
| src/vs/workbench/services/agentHost/electron-browser/agentHostService.ts | Passes correct clientInfo when creating the local agent host client. |
| src/vs/workbench/services/agentHost/browser/editorRemoteAgentHostServiceClient.ts | Supplies clientInfo to remote protocol client based on sessions vs editor window. |
| src/vs/sessions/sessions.web.main.ts | Registers agents-window remote agent host service implementation. |
| src/vs/sessions/sessions.desktop.main.ts | Registers agents-window remote agent host service and removes legacy remote service import. |
| src/vs/sessions/contrib/providers/remoteAgentHost/electron-browser/tunnelAgentHostServiceImpl.ts | Identifies tunnel protocol clients as agents-window clients. |
| src/vs/sessions/contrib/providers/remoteAgentHost/browser/webTunnelAgentHostService.ts | Identifies web tunnel protocol clients as agents-window clients. |
| src/vs/platform/agentHost/test/node/protocolServerHandler.test.ts | Adds reconnect/not-found + client attribution across reconnect test coverage. |
| src/vs/platform/agentHost/test/node/mockAgent.ts | Extends mock agent messaging to carry clientType for assertions. |
| src/vs/platform/agentHost/test/node/agentSideEffects.test.ts | Verifies clientId/clientType forwarding + queued-message attribution + telemetry prop. |
| src/vs/platform/agentHost/test/node/agentHostTelemetryReporter.test.ts | Updates telemetry reporter tests for initiatorClientType on restricted events. |
| src/vs/platform/agentHost/test/node/agentHostGitHubTelemetryRouter.test.ts | Verifies additional properties are merged into routed GitHub telemetry. |
| src/vs/platform/agentHost/test/electron-browser/remoteAgentHostService.test.ts | Ensures protocol clients get correct clientInfo for editor vs agents window. |
| src/vs/platform/agentHost/test/electron-browser/remoteAgentHostProtocolClient.test.ts | Covers initialize including clientInfo and reconnect NotFound fallback to initialize. |
| src/vs/platform/agentHost/node/protocolServerHandler.ts | Stores clientInfo, rejects unknown reconnects, and attributes dispatched actions by client type. |
| src/vs/platform/agentHost/node/copilot/copilotAgentSession.ts | Persists per-turn clientType for telemetry attribution. |
| src/vs/platform/agentHost/node/copilot/copilotAgent.ts | Routes GitHub telemetry with added initiatorClientType derived from current turn. |
| src/vs/platform/agentHost/node/agentSideEffects.ts | Threads clientType through action handling, queued messages, and agent send calls. |
| src/vs/platform/agentHost/node/agentService.ts | Propagates clientType into side effects and clears queued-message sender attribution on disposal. |
| src/vs/platform/agentHost/node/agentHostTelemetryReporter.ts | Adds initiatorClientType to public + restricted telemetry payloads. |
| src/vs/platform/agentHost/node/agentHostGitHubTelemetryRouter.ts | Allows routing with additional merged telemetry properties. |
| src/vs/platform/agentHost/electron-browser/wslRemoteAgentHostServiceImpl.ts | Tags WSL protocol clients with agents-window client info. |
| src/vs/platform/agentHost/electron-browser/sshRemoteAgentHostServiceImpl.ts | Tags SSH protocol clients with agents-window client info. |
| src/vs/platform/agentHost/electron-browser/localAgentHostService.ts | Requires clientInfo and passes it into the protocol client handshake. |
| src/vs/platform/agentHost/common/agentService.ts | Updates agent service interfaces to accept optional clientType. |
| src/vs/platform/agentHost/common/agentHostClientInfo.ts | New helper defining client-info constants + AgentHostClientType mapping. |
| src/vs/platform/agentHost/browser/remoteAgentHostServiceImpl.ts | Adds an agents-window subclass to supply clientInfo into protocol clients. |
| src/vs/platform/agentHost/browser/remoteAgentHostProtocolClient.ts | Sends clientInfo on initialize and falls back to initialize after reconnect NotFound. |
Review details
- Files reviewed: 28/28 changed files
- Comments generated: 3
- Review effort level: Low
Comment on lines
+110
to
+112
| dispatchAction(channel: string, action: SessionAction | TerminalAction | ClientAnnotationsAction | IRootConfigChangedAction, clientId: string, clientSeq: number, _clientType?: AgentHostClientType): void { | ||
| this.handledActions.push(action); | ||
| this.handledClientTypes.push(_clientType); |
Comment on lines
+671
to
+709
| private async _reconnectOrInitialize(lastSeenServerSeq: number, subscriptions: string[]): Promise<CommandMap['reconnect']['result']> { | ||
| try { | ||
| return await this._dispatchRequest<CommandMap['reconnect']['result']>('reconnect', { | ||
| clientId: this._clientId, | ||
| lastSeenServerSeq, | ||
| subscriptions, | ||
| }, { bypassReconnectGate: true }); | ||
| } catch (error) { | ||
| if (!(error instanceof ProtocolError) || error.code !== AhpErrorCodes.NotFound) { | ||
| throw error; | ||
| } | ||
| } | ||
|
|
||
| this._logService.info(`[RemoteAgentHostProtocol] Server forgot client ${this._clientId}; initializing a fresh connection.`); | ||
| const initializeResult = await this._dispatchRequest<CommandMap['initialize']['result']>('initialize', { | ||
| channel: ROOT_STATE_URI, | ||
| protocolVersions: [PROTOCOL_VERSION], | ||
| clientId: this._clientId, | ||
| clientInfo: this._clientInfo, | ||
| initialSubscriptions: subscriptions, | ||
| }, { bypassReconnectGate: true }); | ||
| this._initializeResult.set(initializeResult, undefined); | ||
| this._serverSeq = initializeResult.serverSeq; | ||
| if (initializeResult.defaultDirectory) { | ||
| const directory = initializeResult.defaultDirectory; | ||
| this._defaultDirectory = typeof directory === 'string' ? URI.parse(directory).path : URI.revive(directory).path; | ||
| } | ||
| this._updateTelemetryLevel(); | ||
| this._updateSessionSyncEnabled(); | ||
| this._updateTerminalAutoApproveEnabled(); | ||
| this._updateGlobalAutoApproveEnabled(); | ||
| this._updateAutoReplyEnabled(); | ||
| this._updatePreferLongContextEnabled(); | ||
| this._updateSystemProxyEnabled(); | ||
| this._updateTerminalAutoApproveRules(); | ||
| this._updateCodexEnabled(); | ||
| this._updateDisableRepoInfoTelemetry(); | ||
| return { type: ReconnectResultType.Snapshot, snapshots: initializeResult.snapshots ?? [] }; | ||
| } |
Comment on lines
+779
to
+791
| private _clientTypeForTelemetry(sdkSessionId: string | undefined): AgentHostClientType { | ||
| if (!sdkSessionId) { | ||
| return AgentHostClientType.Unknown; | ||
| } | ||
| for (const entry of this._sessions.values()) { | ||
| for (const chat of entry.allChatSessions()) { | ||
| if (chat.sessionId === sdkSessionId) { | ||
| return chat.currentTurnClientType; | ||
| } | ||
| } | ||
| } | ||
| return AgentHostClientType.Unknown; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
initialize.clientInfoinitiatorClientTypeWhy
An Agent Host process and session can be shared by multiple VS Code windows. Session identity and process-wide common properties therefore cannot reliably identify which window initiated a turn. This adds per-interaction attribution without introducing a new telemetry event.
Validation
npm run typecheck-clientnpm run valid-layers-checkReview notes
Please pay particular attention to the existing CTS event property name, SDK telemetry callback routing, queued-message attribution lifetime, and reconnect fallback behavior.
(Written by Copilot)