From 086501e7d7a02efdc5d91cda5924584a74035ea2 Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 12 Jun 2025 20:52:23 +0200 Subject: [PATCH] move prompt file parser usages to IPromptsService (#251298) --- .../chat/browser/chatAttachmentModel.ts | 2 +- .../chatPromptAttachmentModel.ts | 117 ------------------ ...Collection.ts => chatPromptAttachments.ts} | 80 ++++++------ .../promptToolsCodeLensProvider.ts | 2 +- .../contrib/chat/common/chatModes.ts | 3 +- .../promptContentsProviderBase.ts | 4 +- .../promptSyntax/contentProviders/types.ts | 3 +- .../languageProviders/promptLinkProvider.ts | 2 +- .../promptPathAutocompletion.ts | 2 +- .../promptSyntax/parsers/basePromptParser.ts | 5 +- .../promptSyntax/service/promptsService.ts | 29 +++-- .../service/promptsServiceImpl.ts | 26 +++- .../chat/test/common/mockPromptsService.ts | 8 +- 13 files changed, 95 insertions(+), 188 deletions(-) delete mode 100644 src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentModel.ts rename src/vs/workbench/contrib/chat/browser/chatAttachmentModel/{chatPromptAttachmentsCollection.ts => chatPromptAttachments.ts} (68%) diff --git a/src/vs/workbench/contrib/chat/browser/chatAttachmentModel.ts b/src/vs/workbench/contrib/chat/browser/chatAttachmentModel.ts index 1533fcca6cd..ec2a4e021c6 100644 --- a/src/vs/workbench/contrib/chat/browser/chatAttachmentModel.ts +++ b/src/vs/workbench/contrib/chat/browser/chatAttachmentModel.ts @@ -10,7 +10,7 @@ import { IRange } from '../../../../editor/common/core/range.js'; import { Disposable } from '../../../../base/common/lifecycle.js'; import { IChatRequestFileEntry, IChatRequestVariableEntry, isPromptFileVariableEntry, toPromptFileVariableEntry } from '../common/chatVariableEntries.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; -import { ChatPromptAttachmentsCollection } from './chatAttachmentModel/chatPromptAttachmentsCollection.js'; +import { ChatPromptAttachmentsCollection } from './chatAttachmentModel/chatPromptAttachments.js'; import { IFileService } from '../../../../platform/files/common/files.js'; import { IDialogService } from '../../../../platform/dialogs/common/dialogs.js'; import { ISharedWebContentExtractorService } from '../../../../platform/webContentExtractor/common/webContentExtractor.js'; diff --git a/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentModel.ts b/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentModel.ts deleted file mode 100644 index b88ab8a540a..00000000000 --- a/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentModel.ts +++ /dev/null @@ -1,117 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { URI } from '../../../../../base/common/uri.js'; -import { PromptParser } from '../../common/promptSyntax/parsers/promptParser.js'; -import { BasePromptParser } from '../../common/promptSyntax/parsers/basePromptParser.js'; -import { IPromptContentsProvider } from '../../common/promptSyntax/contentProviders/types.js'; -import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; -import { Disposable } from '../../../../../base/common/lifecycle.js'; - -/** - * Type for a generic prompt parser object. - */ -type TPromptParser = BasePromptParser; - -/** - * Model for a single chat prompt instructions attachment. - */ -export class ChatPromptAttachmentModel extends Disposable { - /** - * Private reference of the underlying prompt instructions - * reference instance. - */ - private readonly _reference: TPromptParser; - - /** - * Get the prompt instructions reference instance. - */ - public get reference(): TPromptParser { - return this._reference; - } - - /** - * Get `URI` for the main reference and `URI`s of all valid child - * references it may contain, including reference of this model itself. - */ - public get references(): readonly URI[] { - const { reference } = this; - const { errorCondition } = reference; - - // return no references if the attachment is disabled - // or if this object itself has an error - if (errorCondition) { - return []; - } - - // otherwise return `URI` for the main reference and - // all valid child `URI` references it may contain - return [ - ...reference.allValidReferences.map(ref => ref.uri), - reference.uri, - ]; - } - - /** - * Get list of all tools associated with the prompt. - * - * Note! This property returns pont-in-time state of the tools metadata - * and does not take into account if the prompt or its nested child - * references are still being resolved. Please use the {@link settled} - * or {@link allSettled} properties if you need to retrieve the final - * list of the tools available. - */ - public get toolsMetadata(): readonly string[] | null { - return this.reference.allToolsMetadata; - } - - /** - * Promise that resolves when the prompt is fully parsed, - * including all its possible nested child references. - */ - public get allSettled(): Promise { - return this.reference.allSettled(); - } - - /** - * Get the top-level error of the prompt instructions - * reference, if any. - */ - public get topError() { - return this.reference.topError; - } - - - constructor( - public readonly uri: URI, - private readonly _onUpdate: () => void, - @IInstantiationService private readonly instantiationService: IInstantiationService, - ) { - super(); - - this._reference = this._register( - this.instantiationService.createInstance( - PromptParser, - this.uri, - // in this case we know that the attached file must have been a - // prompt file, hence we pass the `allowNonPromptFiles` option - // to the provider to allow for non-prompt files to be attached - { allowNonPromptFiles: true }, - ) - ); - - this._register(this._reference.onUpdate(() => this._onUpdate())); - } - - /** - * Start resolving the prompt instructions reference and child references - * that it may contain. - */ - public resolve(): this { - this._reference.start(); - - return this; - } -} diff --git a/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentsCollection.ts b/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachments.ts similarity index 68% rename from src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentsCollection.ts rename to src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachments.ts index af7381fd783..20e1bb26994 100644 --- a/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachmentsCollection.ts +++ b/src/vs/workbench/contrib/chat/browser/chatAttachmentModel/chatPromptAttachments.ts @@ -3,19 +3,19 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancelablePromise, createCancelablePromise } from '../../../../../base/common/async.js'; import { Emitter } from '../../../../../base/common/event.js'; import { Disposable } from '../../../../../base/common/lifecycle.js'; import { ResourceMap } from '../../../../../base/common/map.js'; +import { URI } from '../../../../../base/common/uri.js'; import { ILanguageService } from '../../../../../editor/common/languages/language.js'; import { IModelService } from '../../../../../editor/common/services/model.js'; -import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; import { IChatRequestVariableEntry, IPromptFileVariableEntry, toPromptFileVariableEntry } from '../../common/chatVariableEntries.js'; - -import { ChatPromptAttachmentModel } from './chatPromptAttachmentModel.js'; +import { IPromptParserResult, IPromptsService } from '../../common/promptSyntax/service/promptsService.js'; /** * Model for a collection of prompt instruction attachments. - * See {@linkcode ChatPromptAttachmentModel} for individual attachment. + * Starts */ export class ChatPromptAttachmentsCollection extends Disposable { /** @@ -24,29 +24,38 @@ export class ChatPromptAttachmentsCollection extends Disposable { * See {@linkcode onUpdate}. */ protected _onUpdate = this._register(new Emitter()); + /** * Subscribe to the `onUpdate` event. */ public onUpdate = this._onUpdate.event; - /** * List of all prompt instruction attachments. */ - private _attachments: ResourceMap = new ResourceMap(); + private _attachments = new ResourceMap>(); + + + constructor( + @ILanguageService private readonly languageService: ILanguageService, + @IModelService private readonly modelService: IModelService, + @IPromptsService private readonly promptsService: IPromptsService, + ) { + super(); + } /** * Check if any of the attachments is a prompt file. */ public hasPromptFiles(promptFileLanguageId: string): boolean { - const hasLanguage = ({ uri }: ChatPromptAttachmentModel) => { + const hasLanguage = (uri: URI) => { const model = this.modelService.getModel(uri); const languageId = model ? model.getLanguageId() : this.languageService.guessLanguageIdByFilepathOrFirstLine(uri); return languageId === promptFileLanguageId; }; - for (const child of this._attachments.values()) { - if (hasLanguage(child)) { + for (const uri of this._attachments.keys()) { + if (hasLanguage(uri)) { return true; } } @@ -58,51 +67,25 @@ export class ChatPromptAttachmentsCollection extends Disposable { * nested child references of each attachment explicitly attached by user. */ public async getAttachments(): Promise { - await this.allSettled(); - const result = []; const attachments = [...this._attachments.values()]; - for (const attachment of attachments) { - const { reference } = attachment; + for (const parseResultPromise of attachments) { + const parseResult = await parseResultPromise; // the usual URIs list of prompt instructions is `bottom-up`, therefore // we do the same here - first add all child references of the model - result.push( - ...reference.allValidReferences.map((link) => { - return toPromptFileVariableEntry(link.uri, false); - }), - ); + for (const uri of parseResult.allValidReferences) { + result.push(toPromptFileVariableEntry(uri, false)); + } // then add the root reference of the model itself - result.push(toPromptFileVariableEntry(reference.uri, true)); + result.push(toPromptFileVariableEntry(parseResult.uri, true)); } return result; } - /** - * Promise that resolves when parsing of all attached prompt instruction - * files completes, including parsing of all its possible child references. - */ - async allSettled(): Promise { - const attachments = [...this._attachments.values()]; - - await Promise.allSettled( - attachments.map((attachment) => { - return attachment.allSettled; - }), - ); - } - - constructor( - @IInstantiationService private readonly instantiationService: IInstantiationService, - @ILanguageService private readonly languageService: ILanguageService, - @IModelService private readonly modelService: IModelService, - ) { - super(); - } - /** * Add prompt instruction attachment instances */ @@ -115,8 +98,15 @@ export class ChatPromptAttachmentsCollection extends Disposable { continue; } - const instruction = this.instantiationService.createInstance(ChatPromptAttachmentModel, uri, () => this._onUpdate.fire(entry)); - this._attachments.set(uri, instruction); + const parseResult = createCancelablePromise(token => this.promptsService.parse(uri, token)); + parseResult.then(() => { + this._onUpdate.fire(entry); + }).catch((error) => { + // if parsing fails, we still create an attachment model + // to allow the user to see the error and fix it + console.error(`Failed to parse prompt file ${uri.toString()}:`, error); + }); + this._attachments.set(uri, parseResult); } } @@ -129,7 +119,7 @@ export class ChatPromptAttachmentsCollection extends Disposable { const attachment = this._attachments.get(uri); if (attachment) { this._attachments.delete(uri); - attachment.dispose(); + attachment.cancel(); } return this; @@ -140,7 +130,7 @@ export class ChatPromptAttachmentsCollection extends Disposable { */ public clear(): this { for (const attachment of this._attachments.values()) { - attachment.dispose(); + attachment.cancel(); } this._attachments.clear(); diff --git a/src/vs/workbench/contrib/chat/browser/promptSyntax/promptToolsCodeLensProvider.ts b/src/vs/workbench/contrib/chat/browser/promptSyntax/promptToolsCodeLensProvider.ts index 8f359d3c4c5..68edcd52a3a 100644 --- a/src/vs/workbench/contrib/chat/browser/promptSyntax/promptToolsCodeLensProvider.ts +++ b/src/vs/workbench/contrib/chat/browser/promptSyntax/promptToolsCodeLensProvider.ts @@ -49,7 +49,7 @@ class PromptToolsCodeLensProvider extends Disposable implements CodeLensProvider const parser = this.promptsService.getSyntaxParserFor(model); const { header } = await parser - .start() + .start(token) .settled(); if ((header === undefined) || token.isCancellationRequested) { diff --git a/src/vs/workbench/contrib/chat/common/chatModes.ts b/src/vs/workbench/contrib/chat/common/chatModes.ts index 1d7812c5245..b4a9d447569 100644 --- a/src/vs/workbench/contrib/chat/common/chatModes.ts +++ b/src/vs/workbench/contrib/chat/common/chatModes.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { CancellationToken } from '../../../../base/common/cancellation.js'; import { Emitter, Event } from '../../../../base/common/event.js'; import { Disposable } from '../../../../base/common/lifecycle.js'; import { localize } from '../../../../nls.js'; @@ -49,7 +50,7 @@ export class ChatModeService extends Disposable implements IChatModeService { private async refreshCustomPromptModes(fireChangeEvent?: boolean): Promise { try { - const modes = await this.promptsService.getCustomChatModes(); + const modes = await this.promptsService.getCustomChatModes(CancellationToken.None); this.latestCustomPromptModes = modes.map(customMode => new CustomChatMode(customMode)); this.hasCustomModes.set(modes.length > 0); if (fireChangeEvent) { diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/promptContentsProviderBase.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/promptContentsProviderBase.ts index 7d301ad5545..1f90d5ff59d 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/promptContentsProviderBase.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/promptContentsProviderBase.ts @@ -179,14 +179,14 @@ export abstract class PromptContentsProviderBase< /** * Start producing the prompt contents data. */ - public start(): this { + public start(token?: CancellationToken): this { assert( !this.isDisposed, 'Cannot start contents provider that was already disposed.', ); // `'full'` means "everything has changed" - this.onContentsChanged('full'); + this.onContentsChanged('full', token); // subscribe to the change event emitted by a child class this._register(this.onChangeEmitter.event(this.onContentsChanged, this)); diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/types.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/types.ts index be572215a4f..bec215b1d04 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/types.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/contentProviders/types.ts @@ -9,6 +9,7 @@ import { ResolveError } from '../../promptFileReferenceErrors.js'; import { IDisposable } from '../../../../../../base/common/lifecycle.js'; import { VSBufferReadableStream } from '../../../../../../base/common/buffer.js'; import { PromptsType } from '../promptTypes.js'; +import { CancellationToken } from '../../../../../../base/common/cancellation.js'; /** * Interface for a prompt contents provider. Prompt contents providers are @@ -56,7 +57,7 @@ export interface IPromptContentsProvider extends IDisposable { /** * Start the contents provider to produce the underlying contents. */ - start(): this; + start(token?: CancellationToken): this; /** * Create a new instance of prompt contents provider. diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptLinkProvider.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptLinkProvider.ts index 275682fdc8b..a92e0695b28 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptLinkProvider.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptLinkProvider.ts @@ -42,7 +42,7 @@ export class PromptLinkProvider implements LinkProvider { // start the parser in case it was not started yet, // and wait for it to settle to a final result const { references } = await parser - .start() + .start(token) .settled(); // validate that the cancellation was not yet requested diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptPathAutocompletion.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptPathAutocompletion.ts index 956cd5a6888..8470df895c9 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptPathAutocompletion.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/languageProviders/promptPathAutocompletion.ts @@ -138,7 +138,7 @@ export class PromptPathAutocompletion extends Disposable implements CompletionIt // start the parser in case it was not started yet, // and wait for it to settle to a final result const { references } = await parser - .start() + .start(token) .settled(); // validate that the cancellation was not yet requested diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts index c5436bd295e..7be72d8379f 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/parsers/basePromptParser.ts @@ -39,6 +39,7 @@ import { isPromptOrInstructionsFile } from '../config/promptFileLocations.js'; import { FrontMatterHeader } from '../codecs/base/markdownExtensionsCodec/tokens/frontMatterHeader.js'; import { OpenFailed, NotPromptFile, RecursiveReference, FolderReference, ResolveError } from '../../promptFileReferenceErrors.js'; import { type IPromptContentsProviderOptions, DEFAULT_OPTIONS as CONTENTS_PROVIDER_DEFAULT_OPTIONS } from '../contentProviders/promptContentsProviderBase.js'; +import { CancellationToken } from '../../../../../../base/common/cancellation.js'; /** * Options of the {@link BasePromptParser} class. @@ -511,7 +512,7 @@ export class BasePromptParser /** * Start the prompt parser. */ - public start(): this { + public start(token?: CancellationToken): this { // if already started, nothing to do if (this.started) { return this; @@ -525,7 +526,7 @@ export class BasePromptParser return this; } - this.promptContentsProvider.start(); + this.promptContentsProvider.start(token); return this; } diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsService.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsService.ts index fe706645583..db6bc946c57 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsService.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsService.ts @@ -14,6 +14,7 @@ import { TextModelPromptParser } from '../parsers/textModelPromptParser.js'; import { CancellationToken } from '../../../../../../base/common/cancellation.js'; import { PromptsType } from '../promptTypes.js'; import { createDecorator } from '../../../../../../platform/instantiation/common/instantiation.js'; +import { ITopError } from '../parsers/types.js'; /** * Provides prompt services. @@ -151,9 +152,7 @@ export interface IPromptsService extends IDisposable { * Get a prompt syntax parser for the provided text model. * See {@link TextModelPromptParser} for more info on the parser API. */ - getSyntaxParserFor( - model: ITextModel, - ): TSharedPrompt & { isDisposed: false }; + getSyntaxParserFor(model: ITextModel): TSharedPrompt & { isDisposed: false }; /** * List all available prompt files. @@ -185,9 +184,7 @@ export interface IPromptsService extends IDisposable { * Find all instruction files which have a glob pattern in their * 'applyTo' metadata record that match the provided list of files. */ - findInstructionFilesFor( - fileUris: readonly URI[], - ): Promise; + findInstructionFilesFor(fileUris: readonly URI[]): Promise; /** * Event that is triggered when the list of custom chat modes changes. @@ -197,7 +194,7 @@ export interface IPromptsService extends IDisposable { /** * Finds all available custom chat modes */ - getCustomChatModes(): Promise; + getCustomChatModes(token: CancellationToken): Promise; /** * Gets the metadata for the given prompt file uri. @@ -212,9 +209,13 @@ export interface IPromptsService extends IDisposable { * each of the provided files, therefore the result is a number * of metadata trees, one for each file. */ - getAllMetadata( - promptUris: readonly URI[], - ): Promise; + getAllMetadata(promptUris: readonly URI[]): Promise; + + /** + * Parses the provided URI + * @param uris + */ + parse(uri: URI, token: CancellationToken): Promise; } export interface IChatPromptSlashCommand { @@ -222,3 +223,11 @@ export interface IChatPromptSlashCommand { readonly detail: string; readonly promptPath?: IPromptPath; } + + +export interface IPromptParserResult { + readonly uri: URI; + readonly metadata: TMetadata | null; + readonly topError: ITopError | undefined; + readonly allValidReferences: readonly URI[]; +} diff --git a/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts b/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts index 2c7dd5e5030..31f3b1d8293 100644 --- a/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts +++ b/src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts @@ -25,7 +25,7 @@ import { IModelService } from '../../../../../../editor/common/services/model.js import { CancellationToken } from '../../../../../../base/common/cancellation.js'; import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js'; import { IUserDataProfileService } from '../../../../../services/userDataProfile/common/userDataProfile.js'; -import type { IChatPromptSlashCommand, ICustomChatMode, IMetadata, IPromptPath, IPromptsService, TPromptsStorage } from './promptsService.js'; +import type { IChatPromptSlashCommand, ICustomChatMode, IMetadata, IPromptParserResult, IPromptPath, IPromptsService, TPromptsStorage } from './promptsService.js'; import { getCleanPromptName, PROMPT_FILE_EXTENSION } from '../config/promptFileLocations.js'; /** @@ -190,8 +190,8 @@ export class PromptsService extends Disposable implements IPromptsService { }); } - public async getCustomChatModes(): Promise { - const modeFiles = (await this.listPromptFiles(PromptsType.mode, CancellationToken.None)) + public async getCustomChatModes(token: CancellationToken): Promise { + const modeFiles = (await this.listPromptFiles(PromptsType.mode, token)) .map(modeFile => modeFile.uri); const metadataList = await Promise.all( @@ -204,7 +204,7 @@ export class PromptsService extends Disposable implements IPromptsService { PromptParser, uri, { allowNonPromptFiles: true }, - ).start(); + ).start(token); await parser.settled(); @@ -230,6 +230,24 @@ export class PromptsService extends Disposable implements IPromptsService { return metadataList; } + public async parse(uri: URI, token: CancellationToken): Promise { + let parser: PromptParser | undefined; + try { + parser = this.instantiationService.createInstance(PromptParser, uri, { allowNonPromptFiles: true }).start(token); + await parser.settled(); + // make a copy, to avoid leaking the parser instance + return { + uri: parser.uri, + metadata: parser.metadata, + topError: parser.topError, + allValidReferences: parser.allValidReferences.map(ref => ref.uri) + }; + } finally { + parser?.dispose(); + } + } + + public async findInstructionFilesFor(files: readonly URI[]): Promise { const instructionFiles = await this.listPromptFiles(PromptsType.instructions, CancellationToken.None); if (instructionFiles.length === 0) { diff --git a/src/vs/workbench/contrib/chat/test/common/mockPromptsService.ts b/src/vs/workbench/contrib/chat/test/common/mockPromptsService.ts index 1d7162f1154..810e953918e 100644 --- a/src/vs/workbench/contrib/chat/test/common/mockPromptsService.ts +++ b/src/vs/workbench/contrib/chat/test/common/mockPromptsService.ts @@ -8,7 +8,8 @@ import { URI } from '../../../../../base/common/uri.js'; import { ITextModel } from '../../../../../editor/common/model.js'; import { PromptsType } from '../../common/promptSyntax/promptTypes.js'; import { TextModelPromptParser } from '../../common/promptSyntax/parsers/textModelPromptParser.js'; -import { IChatPromptSlashCommand, ICustomChatMode, IMetadata, IPromptPath, IPromptsService } from '../../common/promptSyntax/service/promptsService.js'; +import { IChatPromptSlashCommand, ICustomChatMode, IMetadata, IPromptParserResult, IPromptPath, IPromptsService } from '../../common/promptSyntax/service/promptsService.js'; +import { CancellationToken } from '../../../../../base/common/cancellation.js'; export class MockPromptsService implements IPromptsService { @@ -42,7 +43,10 @@ export class MockPromptsService implements IPromptsService { throw new Error('Method not implemented.'); } onDidChangeCustomChatModes: Event = Event.None; - getCustomChatModes(): Promise { + getCustomChatModes(token: CancellationToken): Promise { + throw new Error('Method not implemented.'); + } + parse(uri: URI, token: CancellationToken): Promise { throw new Error('Method not implemented.'); } dispose(): void { }