Skip to content

Fix up interactiveSessionProviderInvoked ttft telemetry #249695

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 28, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHostChatAgents2.ts
Original file line number Diff line number Diff line change
@@ -107,7 +107,7 @@ class ChatAgentResponseStream {

const _report = (progress: IChatProgressDto, task?: (progress: vscode.Progress<vscode.ChatResponseWarningPart | vscode.ChatResponseReferencePart>) => Thenable<string | void>) => {
// Measure the time to the first progress update with real markdown content
if (typeof this._firstProgress === 'undefined' && (progress.kind === 'markdownContent' || progress.kind === 'markdownVuln')) {
if (typeof this._firstProgress === 'undefined' && (progress.kind === 'markdownContent' || progress.kind === 'markdownVuln' || progress.kind === 'prepareToolInvocation')) {
this._firstProgress = this._stopWatch.elapsed();
}

18 changes: 14 additions & 4 deletions src/vs/workbench/contrib/chat/common/chatServiceImpl.ts
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ import { ChatSessionStore, IChatTransfer2 } from './chatSessionStore.js';
import { IChatSlashCommandService } from './chatSlashCommands.js';
import { IChatTransferService } from './chatTransferService.js';
import { ChatAgentLocation, ChatConfiguration, ChatMode } from './constants.js';
import { ChatMessageRole, IChatMessage } from './languageModels.js';
import { ChatMessageRole, IChatMessage, ILanguageModelsService } from './languageModels.js';
import { ILanguageModelToolsService } from './languageModelToolsService.js';

const serializedChatKey = 'interactive.sessions';
@@ -60,6 +60,7 @@ type ChatProviderInvokedEvent = {
isParticipantDetected: boolean;
enableCommandDetection: boolean;
attachmentKinds: string[];
model: string | undefined;
};

type ChatProviderInvokedClassification = {
@@ -77,6 +78,7 @@ type ChatProviderInvokedClassification = {
isParticipantDetected: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the participant was automatically detected.' };
enableCommandDetection: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether participation detection was disabled for this invocation.' };
attachmentKinds: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The types of variables/attachments that the user included with their query.' };
model: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The model used to generate the response.' };
owner: 'roblourens';
comment: 'Provides insight into the performance of Chat agents.';
};
@@ -157,6 +159,7 @@ export class ChatService extends Disposable implements IChatService {
@IConfigurationService private readonly configurationService: IConfigurationService,
@IWorkbenchAssignmentService private readonly experimentService: IWorkbenchAssignmentService,
@IChatTransferService private readonly chatTransferService: IChatTransferService,
@ILanguageModelsService private readonly languageModelsService: ILanguageModelsService,
) {
super();

@@ -713,7 +716,8 @@ export class ChatService extends Disposable implements IChatService {
numCodeBlocks: getCodeBlocks(request.response?.response.toString() ?? '').length,
isParticipantDetected: !!detectedAgent,
enableCommandDetection,
attachmentKinds: this.attachmentKindsForTelemetry(request.variableData)
attachmentKinds: this.attachmentKindsForTelemetry(request.variableData),
model: this.resolveModelId(options?.userSelectedModelId),
});

model.cancelRequest(request);
@@ -850,7 +854,8 @@ export class ChatService extends Disposable implements IChatService {
location,
citations: request.response?.codeCitations.length ?? 0,
numCodeBlocks: getCodeBlocks(request.response?.response.toString() ?? '').length,
attachmentKinds: this.attachmentKindsForTelemetry(request.variableData)
attachmentKinds: this.attachmentKindsForTelemetry(request.variableData),
model: this.resolveModelId(options?.userSelectedModelId),
});
model.setResponse(request, rawResult);
completeResponseCreated();
@@ -885,7 +890,8 @@ export class ChatService extends Disposable implements IChatService {
numCodeBlocks: 0,
enableCommandDetection,
isParticipantDetected: !!detectedAgent,
attachmentKinds: this.attachmentKindsForTelemetry(request.variableData)
attachmentKinds: this.attachmentKindsForTelemetry(request.variableData),
model: this.resolveModelId(options?.userSelectedModelId)
});
this.logService.error(`Error while handling chat request: ${toErrorMessage(err, true)}`);
if (request) {
@@ -911,6 +917,10 @@ export class ChatService extends Disposable implements IChatService {
};
}

private resolveModelId(userSelectedModelId: string | undefined): string | undefined {
return userSelectedModelId && this.languageModelsService.lookupLanguageModel(userSelectedModelId)?.id;
}

private prepareContext(attachedContextVariables: IChatRequestVariableEntry[] | undefined): IChatRequestVariableEntry[] {
attachedContextVariables ??= [];

Original file line number Diff line number Diff line change
@@ -4,36 +4,38 @@
*--------------------------------------------------------------------------------------------*/

import assert from 'assert';
import { workbenchInstantiationService } from '../../../../test/browser/workbenchTestServices.js';
import { ChatEditingService } from '../../browser/chatEditing/chatEditingServiceImpl.js';
import { CancellationToken } from '../../../../../base/common/cancellation.js';
import { Disposable, DisposableStore, IDisposable } from '../../../../../base/common/lifecycle.js';
import { ServiceCollection } from '../../../../../platform/instantiation/common/serviceCollection.js';
import { IMultiDiffSourceResolver, IMultiDiffSourceResolverService } from '../../../multiDiffEditor/browser/multiDiffSourceResolverService.js';
import { waitForState } from '../../../../../base/common/observable.js';
import { isEqual } from '../../../../../base/common/resources.js';
import { assertType } from '../../../../../base/common/types.js';
import { URI } from '../../../../../base/common/uri.js';
import { mock } from '../../../../../base/test/common/mock.js';
import { IChatService } from '../../common/chatService.js';
import { SyncDescriptor } from '../../../../../platform/instantiation/common/descriptors.js';
import { ChatService } from '../../common/chatServiceImpl.js';
import { IChatEditingService } from '../../common/chatEditingService.js';
import { assertThrowsAsync, ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
import { IChatVariablesService } from '../../common/chatVariables.js';
import { MockChatVariablesService } from '../common/mockChatVariables.js';
import { ChatAgentService, IChatAgentData, IChatAgentImplementation, IChatAgentService } from '../../common/chatAgents.js';
import { IChatSlashCommandService } from '../../common/chatSlashCommands.js';
import { Range } from '../../../../../editor/common/core/range.js';
import { IModelService } from '../../../../../editor/common/services/model.js';
import { ITextModelService } from '../../../../../editor/common/services/resolverService.js';
import { SyncDescriptor } from '../../../../../platform/instantiation/common/descriptors.js';
import { ServiceCollection } from '../../../../../platform/instantiation/common/serviceCollection.js';
import { IWorkbenchAssignmentService } from '../../../../services/assignment/common/assignmentService.js';
import { NullWorkbenchAssignmentService } from '../../../../services/assignment/test/common/nullAssignmentService.js';
import { CancellationToken } from '../../../../../base/common/cancellation.js';
import { nullExtensionDescription } from '../../../../services/extensions/common/extensions.js';
import { ITextModelService } from '../../../../../editor/common/services/resolverService.js';
import { IModelService } from '../../../../../editor/common/services/model.js';
import { URI } from '../../../../../base/common/uri.js';
import { assertType } from '../../../../../base/common/types.js';
import { isEqual } from '../../../../../base/common/resources.js';
import { waitForState } from '../../../../../base/common/observable.js';
import { INotebookService } from '../../../notebook/common/notebookService.js';
import { Range } from '../../../../../editor/common/core/range.js';
import { ChatAgentLocation, ChatMode } from '../../common/constants.js';
import { workbenchInstantiationService } from '../../../../test/browser/workbenchTestServices.js';
import { IMultiDiffSourceResolver, IMultiDiffSourceResolverService } from '../../../multiDiffEditor/browser/multiDiffSourceResolverService.js';
import { NotebookTextModel } from '../../../notebook/common/model/notebookTextModel.js';
import { INotebookService } from '../../../notebook/common/notebookService.js';
import { ChatEditingService } from '../../browser/chatEditing/chatEditingServiceImpl.js';
import { ChatAgentService, IChatAgentData, IChatAgentImplementation, IChatAgentService } from '../../common/chatAgents.js';
import { IChatEditingService } from '../../common/chatEditingService.js';
import { IChatService } from '../../common/chatService.js';
import { ChatService } from '../../common/chatServiceImpl.js';
import { IChatSlashCommandService } from '../../common/chatSlashCommands.js';
import { ChatTransferService, IChatTransferService } from '../../common/chatTransferService.js';
import { IChatVariablesService } from '../../common/chatVariables.js';
import { ChatAgentLocation, ChatMode } from '../../common/constants.js';
import { ILanguageModelsService } from '../../common/languageModels.js';
import { NullLanguageModelsService } from '../common/languageModels.js';
import { MockChatVariablesService } from '../common/mockChatVariables.js';

function getAgentData(id: string): IChatAgentData {
return {
@@ -67,6 +69,7 @@ suite('ChatEditingService', function () {
collection.set(IChatTransferService, new SyncDescriptor(ChatTransferService));
collection.set(IChatEditingService, new SyncDescriptor(ChatEditingService));
collection.set(IChatService, new SyncDescriptor(ChatService));
collection.set(ILanguageModelsService, new SyncDescriptor(NullLanguageModelsService));
collection.set(IMultiDiffSourceResolverService, new class extends mock<IMultiDiffSourceResolverService>() {
override registerResolver(_resolver: IMultiDiffSourceResolver): IDisposable {
return Disposable.None;
40 changes: 40 additions & 0 deletions src/vs/workbench/contrib/chat/test/common/languageModels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { CancellationToken } from '../../../../../base/common/cancellation.js';
import { Event } from '../../../../../base/common/event.js';
import { Disposable, IDisposable } from '../../../../../base/common/lifecycle.js';
import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js';
import { IChatMessage, ILanguageModelChat, ILanguageModelChatMetadata, ILanguageModelChatResponse, ILanguageModelChatSelector, ILanguageModelsService } from '../../common/languageModels.js';

export class NullLanguageModelsService implements ILanguageModelsService {
_serviceBrand: undefined;

onDidChangeLanguageModels = Event.None;

getLanguageModelIds(): string[] {
return [];
}

lookupLanguageModel(identifier: string): ILanguageModelChatMetadata | undefined {
return undefined;
}

async selectLanguageModels(selector: ILanguageModelChatSelector): Promise<string[]> {
return [];
}

registerLanguageModelChat(identifier: string, provider: ILanguageModelChat): IDisposable {
return Disposable.None;
}

sendChatRequest(identifier: string, from: ExtensionIdentifier, messages: IChatMessage[], options: { [name: string]: any }, token: CancellationToken): Promise<ILanguageModelChatResponse> {
throw new Error('Method not implemented.');
}

computeTokenLength(identifier: string, message: string | IChatMessage, token: CancellationToken): Promise<number> {
throw new Error('Method not implemented.');
}
}
Original file line number Diff line number Diff line change
@@ -64,6 +64,8 @@ import { IObservable, constObservable } from '../../../../../base/common/observa
import { IChatEditingService, IChatEditingSession } from '../../../chat/common/chatEditingService.js';
import { ChatAgentLocation, ChatMode } from '../../../chat/common/constants.js';
import { ChatTransferService, IChatTransferService } from '../../../chat/common/chatTransferService.js';
import { NullLanguageModelsService } from '../../../chat/test/common/languageModels.js';
import { ILanguageModelsService } from '../../../chat/common/languageModels.js';

suite('InlineChatSession', function () {

@@ -96,6 +98,7 @@ suite('InlineChatSession', function () {
[IChatAgentService, new SyncDescriptor(ChatAgentService)],
[IContextKeyService, contextKeyService],
[IDiffProviderFactoryService, new SyncDescriptor(TestDiffProviderFactoryService)],
[ILanguageModelsService, new SyncDescriptor(NullLanguageModelsService)],
[IInlineChatSessionService, new SyncDescriptor(InlineChatSessionServiceImpl)],
[ICommandService, new SyncDescriptor(TestCommandService)],
[ILanguageModelToolsService, new MockLanguageModelToolsService()],
Loading
Oops, something went wrong.