Skip to content

agentHost: Attribute telemetry to initiating window#327417

Draft
roblourens wants to merge 1 commit into
mainfrom
roblou/agents/add-telemetry-agents-window-usage
Draft

agentHost: Attribute telemetry to initiating window#327417
roblourens wants to merge 1 commit into
mainfrom
roblou/agents/add-telemetry-agents-window-usage

Conversation

@roblourens

Copy link
Copy Markdown
Member

Summary

  • identify editor and Agents window AHP clients through initialize.clientInfo
  • decorate existing Agent Host and Copilot CTS telemetry with initiatorClientType
  • preserve the initiating client for queued turns
  • retain attribution across reconnects, falling back to a fresh initialize when the host no longer remembers the client

Why

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-client
  • npm run valid-layers-check
  • hygiene checks
  • 712 targeted Agent Host tests, plus focused reconnect/service tests

Review 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)

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>
Copilot AI review requested due to automatic review settings July 24, 2026 23:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 agentHostClientInfo utilities and threads clientInfo through local/remote/tunnel/WSL/SSH protocol clients and sessions.
  • Persists clientInfo on the protocol server across reconnects, derives AgentHostClientType, and forwards it through action dispatch + queued-message consumption.
  • Extends Agent Host + CTS/GitHub telemetry routing to include initiatorClientType, plus reconnect fallback to re-initialize when 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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants