Path: blob/main/src/vs/workbench/contrib/chat/browser/createSlashCommandsUsageTracker.ts
13401 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Disposable } from '../../../../base/common/lifecycle.js';6import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.js';7import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';8import { IChatService } from '../common/chatService/chatService.js';9import { ChatContextKeys } from '../common/actions/chatContextKeys.js';10import { ChatRequestSlashCommandPart } from '../common/requestParser/chatParserTypes.js';1112export class CreateSlashCommandsUsageTracker extends Disposable {13private static readonly _USED_CREATE_SLASH_COMMANDS_KEY = 'chat.tips.usedCreateSlashCommands';1415constructor(16private readonly _chatService: IChatService,17private readonly _storageService: IStorageService,18private readonly _getActiveContextKeyService: () => IContextKeyService | undefined,19) {20super();2122this._register(this._chatService.onDidSubmitRequest(e => {23const message = e.message ?? this._chatService.getSession(e.chatSessionResource)?.lastRequest?.message;24if (!message) {25return;26}2728for (const part of message.parts) {29if (part.kind === ChatRequestSlashCommandPart.Kind) {30const slash = part as ChatRequestSlashCommandPart;31if (CreateSlashCommandsUsageTracker._isCreateSlashCommand(slash.slashCommand.command)) {32this._markUsed();33return;34}35}36}3738// Fallback when parsing doesn't produce a slash command part.39const trimmed = message.text.trimStart();40const match = /^\/(create-(?:instructions|prompt|agent|skill))(?:\s|$)/.exec(trimmed);41if (match && CreateSlashCommandsUsageTracker._isCreateSlashCommand(match[1])) {42this._markUsed();43}44}));45}4647syncContextKey(contextKeyService: IContextKeyService): void {48const used = this._storageService.getBoolean(CreateSlashCommandsUsageTracker._USED_CREATE_SLASH_COMMANDS_KEY, StorageScope.APPLICATION, false);49ChatContextKeys.hasUsedCreateSlashCommands.bindTo(contextKeyService).set(used);50}5152private _markUsed(): void {53if (this._storageService.getBoolean(CreateSlashCommandsUsageTracker._USED_CREATE_SLASH_COMMANDS_KEY, StorageScope.APPLICATION, false)) {54return;55}5657this._storageService.store(CreateSlashCommandsUsageTracker._USED_CREATE_SLASH_COMMANDS_KEY, true, StorageScope.APPLICATION, StorageTarget.MACHINE);5859const contextKeyService = this._getActiveContextKeyService();60if (contextKeyService) {61ChatContextKeys.hasUsedCreateSlashCommands.bindTo(contextKeyService).set(true);62}63}6465private static _isCreateSlashCommand(command: string): boolean {66switch (command) {67case 'create-instructions':68case 'create-prompt':69case 'create-agent':70case 'create-skill':71return true;72default:73return false;74}75}76}777879