From f29ed30fd7f427ddd0d1579d021ceefa82d199e9 Mon Sep 17 00:00:00 2001 From: Oleg Solomko Date: Wed, 11 Dec 2024 10:01:18 -0800 Subject: [PATCH] [prompt snippets]: revert changes for the `ImplicitContext` --- src/vs/base/common/codecs/baseDecoder.ts | 6 +- .../types/TStreamListenerEventNames.d.ts | 4 - .../attachments/implicitContextAttachment.ts | 41 +----- .../contrib/chat/browser/chatInputPart.ts | 130 ++++++++++++------ .../contrib/chat/browser/chatWidget.ts | 2 +- .../browser/contrib/chatDynamicVariables.ts | 23 +--- .../browser/contrib/chatImplicitContext.ts | 85 +----------- 7 files changed, 108 insertions(+), 183 deletions(-) delete mode 100644 src/vs/base/common/codecs/types/TStreamListenerEventNames.d.ts diff --git a/src/vs/base/common/codecs/baseDecoder.ts b/src/vs/base/common/codecs/baseDecoder.ts index 53612a47cc50a..5404e3df0bf42 100644 --- a/src/vs/base/common/codecs/baseDecoder.ts +++ b/src/vs/base/common/codecs/baseDecoder.ts @@ -8,7 +8,11 @@ import { Emitter } from '../event.js'; import { ReadableStream } from '../stream.js'; import { AsyncDecoder } from './asyncDecoder.js'; import { Disposable, IDisposable } from '../lifecycle.js'; -import { TStreamListenerNames } from './types/TStreamListenerEventNames.js'; + +/** + * Event names of {@link ReadableStream} stream. + */ +export type TStreamListenerNames = 'data' | 'error' | 'end'; /** * Base decoder class that can be used to convert stream messages data type diff --git a/src/vs/base/common/codecs/types/TStreamListenerEventNames.d.ts b/src/vs/base/common/codecs/types/TStreamListenerEventNames.d.ts deleted file mode 100644 index f0b56f309c6f9..0000000000000 --- a/src/vs/base/common/codecs/types/TStreamListenerEventNames.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Event names of {@link ReadableStream} stream. - */ -export type TStreamListenerNames = 'data' | 'error' | 'end'; diff --git a/src/vs/workbench/contrib/chat/browser/attachments/implicitContextAttachment.ts b/src/vs/workbench/contrib/chat/browser/attachments/implicitContextAttachment.ts index f1695456cd496..73ab2960823fa 100644 --- a/src/vs/workbench/contrib/chat/browser/attachments/implicitContextAttachment.ts +++ b/src/vs/workbench/contrib/chat/browser/attachments/implicitContextAttachment.ts @@ -8,7 +8,6 @@ import { StandardMouseEvent } from '../../../../../base/browser/mouseEvent.js'; import { Button } from '../../../../../base/browser/ui/button/button.js'; import { getDefaultHoverDelegate } from '../../../../../base/browser/ui/hover/hoverDelegateFactory.js'; import { Codicon } from '../../../../../base/common/codicons.js'; -import { IMarkdownString, MarkdownString } from '../../../../../base/common/htmlContent.js'; import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js'; import { basename, dirname } from '../../../../../base/common/resources.js'; import { URI } from '../../../../../base/common/uri.js'; @@ -24,7 +23,7 @@ import { IHoverService } from '../../../../../platform/hover/browser/hover.js'; import { ILabelService } from '../../../../../platform/label/common/label.js'; import { ResourceLabels } from '../../../../browser/labels.js'; import { ResourceContextKey } from '../../../../common/contextkeys.js'; -import { ChatImplicitContext } from '../contrib/chatImplicitContext.js'; +import { IChatRequestImplicitVariableEntry } from '../../common/chatModel.js'; export class ImplicitContextAttachmentWidget extends Disposable { public readonly domNode: HTMLElement; @@ -32,7 +31,7 @@ export class ImplicitContextAttachmentWidget extends Disposable { private readonly renderDisposables = this._register(new DisposableStore()); constructor( - private readonly attachment: ChatImplicitContext, + private readonly attachment: IChatRequestImplicitVariableEntry, private readonly resourceLabels: ResourceLabels, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IContextMenuService private readonly contextMenuService: IContextMenuService, @@ -63,26 +62,20 @@ export class ImplicitContextAttachmentWidget extends Disposable { const friendlyName = `${fileBasename} ${fileDirname}`; const ariaLabel = range ? localize('chat.fileAttachmentWithRange', "Attached file, {0}, line {1} to line {2}", friendlyName, range.startLineNumber, range.endLineNumber) : localize('chat.fileAttachment', "Attached file, {0}", friendlyName); + const uriLabel = this.labelService.getUriLabel(file, { relative: true }); const currentFile = localize('openEditor', "Current file context"); const inactive = localize('enableHint', "disabled"); - const currentFileHint = new MarkdownString(currentFile + (this.attachment.enabled ? '' : ` (${inactive})`)); - - const title = [currentFileHint, ...this.getUriLabel(file)] - .map((markdown) => { - return markdown.value; - }) - .join('\n'); - + const currentFileHint = currentFile + (this.attachment.enabled ? '' : ` (${inactive})`); + const title = `${currentFileHint}\n${uriLabel}`; label.setFile(file, { fileKind: FileKind.FILE, hidePath: true, range, - title, + title }); this.domNode.ariaLabel = ariaLabel; this.domNode.tabIndex = 0; - - const hintElement = dom.append(this.domNode, dom.$('span.chat-implicit-hint', undefined, localize('current file', 'Current file'))); + const hintElement = dom.append(this.domNode, dom.$('span.chat-implicit-hint', undefined, 'Current file')); this._register(this.hoverService.setupManagedHover(getDefaultHoverDelegate('element'), hintElement, title)); const buttonMsg = this.attachment.enabled ? localize('disable', "Disable current file context") : localize('enable', "Enable current file context"); @@ -113,24 +106,4 @@ export class ImplicitContextAttachmentWidget extends Disposable { }); })); } - - /** - * Get file URIs label, including its possible nested file references. - */ - private getUriLabel( - file: URI, - ): IMarkdownString[] { - const result = [new MarkdownString( - `- ${this.labelService.getUriLabel(file, { relative: true })}`, - )]; - - // if file is a prompt that references other files, add them to the label - for (const child of this.attachment.validFileReferenceUris) { - result.push(new MarkdownString( - ` - ${this.labelService.getUriLabel(child, { relative: true })}`, - )); - } - - return result; - } } diff --git a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts index 859239e8a454e..e381b2e9e3446 100644 --- a/src/vs/workbench/contrib/chat/browser/chatInputPart.ts +++ b/src/vs/workbench/contrib/chat/browser/chatInputPart.ts @@ -13,7 +13,7 @@ import { Button } from '../../../../base/browser/ui/button/button.js'; import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js'; import { IHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegate.js'; import { getBaseLayerHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegate2.js'; -import { createInstantHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js'; +import { createInstantHoverDelegate, getDefaultHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js'; import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js'; import { renderLabelWithIcons } from '../../../../base/browser/ui/iconLabel/iconLabels.js'; import { ProgressBar } from '../../../../base/browser/ui/progressbar/progressbar.js'; @@ -24,7 +24,7 @@ import { Codicon } from '../../../../base/common/codicons.js'; import { Emitter, Event } from '../../../../base/common/event.js'; import { HistoryNavigator2 } from '../../../../base/common/history.js'; import { KeyCode } from '../../../../base/common/keyCodes.js'; -import { Disposable, DisposableStore, IDisposable, MutableDisposable } from '../../../../base/common/lifecycle.js'; +import { Disposable, DisposableStore, IDisposable, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js'; import { ResourceSet } from '../../../../base/common/map.js'; import { basename, dirname } from '../../../../base/common/path.js'; import { isMacintosh } from '../../../../base/common/platform.js'; @@ -37,10 +37,13 @@ import { IDimension } from '../../../../editor/common/core/dimension.js'; import { IPosition } from '../../../../editor/common/core/position.js'; import { IRange, Range } from '../../../../editor/common/core/range.js'; import { isLocation } from '../../../../editor/common/languages.js'; +import { ILanguageService } from '../../../../editor/common/languages/language.js'; import { ITextModel } from '../../../../editor/common/model.js'; +import { getIconClasses } from '../../../../editor/common/services/getIconClasses.js'; import { IModelService } from '../../../../editor/common/services/model.js'; import { ITextModelService } from '../../../../editor/common/services/resolverService.js'; import { CopyPasteController } from '../../../../editor/contrib/dropOrPasteInto/browser/copyPasteController.js'; +import { DropIntoEditorController } from '../../../../editor/contrib/dropOrPasteInto/browser/dropIntoEditorController.js'; import { ContentHoverController } from '../../../../editor/contrib/hover/browser/contentHoverController.js'; import { GlyphHoverController } from '../../../../editor/contrib/hover/browser/glyphHoverController.js'; import { SuggestController } from '../../../../editor/contrib/suggest/browser/suggestController.js'; @@ -62,6 +65,7 @@ import { IHoverService } from '../../../../platform/hover/browser/hover.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js'; import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; +import { ILabelService } from '../../../../platform/label/common/label.js'; import { WorkbenchList } from '../../../../platform/list/browser/listService.js'; import { ILogService } from '../../../../platform/log/common/log.js'; import { INotificationService } from '../../../../platform/notification/common/notification.js'; @@ -76,8 +80,8 @@ import { getSimpleCodeEditorWidgetOptions, getSimpleEditorOptions, setupSimpleEd import { revealInSideBarCommand } from '../../files/browser/fileActions.contribution.js'; import { ChatAgentLocation, IChatAgentService } from '../common/chatAgents.js'; import { ChatContextKeys } from '../common/chatContextKeys.js'; -import { ChatEditingSessionState, IChatEditingService, IChatEditingSession, WorkingSetEntryState } from '../common/chatEditingService.js'; -import { IBaseChatRequestVariableEntry, IChatRequestVariableEntry } from '../common/chatModel.js'; +import { ChatEditingSessionState, IChatEditingService, IChatEditingSession, WorkingSetEntryRemovalReason, WorkingSetEntryState } from '../common/chatEditingService.js'; +import { IChatRequestVariableEntry, isPasteVariableEntry } from '../common/chatModel.js'; import { ChatRequestDynamicVariablePart } from '../common/chatParserTypes.js'; import { IChatFollowup } from '../common/chatService.js'; import { IChatResponseViewModel } from '../common/chatViewModel.js'; @@ -146,29 +150,10 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge return this._attachmentModel; } - public getAttachedAndImplicitContext( - chatWidget: IChatWidget, - ): IChatRequestVariableEntry[] { + public getAttachedAndImplicitContext(chatWidget: IChatWidget): IChatRequestVariableEntry[] { const contextArr = [...this.attachmentModel.attachments]; - - if (this._implicitContext?.enabled && this._implicitContext.value) { - const mainEntry = this._implicitContext.toBaseEntry(); - - contextArr.push(mainEntry); - - // if the implicit context is a file, it can have nested - // file references that should be included in the context - if (this._implicitContext.validFileReferenceUris) { - const childReferences = this._implicitContext.validFileReferenceUris - .map((uri): IBaseChatRequestVariableEntry => { - return { - ...mainEntry, - name: `file:${basename(uri.path)}`, - value: uri, - }; - }); - contextArr.push(...childReferences); - } + if (this.implicitContext?.enabled && this.implicitContext.value) { + contextArr.push(this.implicitContext.toBaseEntry()); } // factor in nested references of dynamic variables into the implicit attached context @@ -308,6 +293,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge getContribsInputState: () => any, @IChatWidgetHistoryService private readonly historyService: IChatWidgetHistoryService, @IModelService private readonly modelService: IModelService, + @ILanguageService private readonly languageService: ILanguageService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IConfigurationService private readonly configurationService: IConfigurationService, @@ -324,6 +310,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge @IThemeService private readonly themeService: IThemeService, @ITextModelService private readonly textModelResolverService: ITextModelService, @IStorageService private readonly storageService: IStorageService, + @ILabelService private readonly labelService: ILabelService, ) { super(); @@ -621,9 +608,8 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge const toolbarsContainer = elements.inputToolbars; this.chatEditingSessionWidgetContainer = elements.chatEditingSessionWidgetContainer; this.renderAttachedContext(); - - if (this.options.enableImplicitContext && !this._implicitContext) { - this._implicitContext = this._register(this.instantiationService.createInstance(ChatImplicitContext)); + if (this.options.enableImplicitContext) { + this._implicitContext = this._register(new ChatImplicitContext()); this._register(this._implicitContext.onDidChangeValue(() => this._handleAttachedContextChange())); } @@ -696,6 +682,10 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this._onDidBlur.fire(); })); + this._register(this._inputEditor.onDidBlurEditorWidget(() => { + CopyPasteController.get(this._inputEditor)?.clearWidgets(); + DropIntoEditorController.get(this._inputEditor)?.clearWidgets(); + })); const hoverDelegate = this._register(createInstantHoverDelegate()); @@ -907,24 +897,25 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge } else if (isPasteVariableEntry(attachment)) { ariaLabel = localize('chat.attachment', "Attached context, {0}", attachment.name); - const hoverContent: IManagedHoverTooltipMarkdownString = { - markdown: { - value: `\`\`\`${attachment.language}\n${attachment.code}\n\`\`\``, - }, - markdownNotSupportedFallback: attachment.code, - }; - const classNames = ['file-icon', `${attachment.language}-lang-file-icon`]; if (attachment.copiedFrom) { resource = attachment.copiedFrom.uri; range = attachment.copiedFrom.range; - label.setFile(attachment.copiedFrom.uri, { extraClasses: classNames }); + const filename = basename(resource.path); + label.setLabel(filename, undefined, { extraClasses: classNames }); } else { label.setLabel(attachment.fileName, undefined, { extraClasses: classNames }); } widget.appendChild(dom.$('span.attachment-additional-info', {}, `Pasted ${attachment.pastedLines}`)); widget.style.position = 'relative'; + + const hoverContent: IManagedHoverTooltipMarkdownString = { + markdown: { + value: `${attachment.copiedFrom ? this.labelService.getUriLabel(attachment.copiedFrom.uri, { relative: true }) : attachment.fileName}\n\n---\n\n\`\`\`${attachment.language}\n\n${attachment.code}\n\`\`\``, + }, + markdownNotSupportedFallback: attachment.code, + }; store.add(this.hoverService.setupManagedHover(hoverDelegate, widget, hoverContent, { trapFocus: true })); this.attachButtonAndDisposables(widget, index, attachment, hoverDelegate); @@ -945,7 +936,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge if (attachment.kind === 'symbol') { const scopedContextKeyService = store.add(this.contextKeyService.createScoped(widget)); - store.add(this.instantiationService.invokeFunction(accessor => hookUpSymbolAttachmentDragAndContextMenu(accessor, widget, scopedContextKeyService, attachment, MenuId.ChatInputSymbolAttachmentContext))); + store.add(this.instantiationService.invokeFunction(accessor => hookUpSymbolAttachmentDragAndContextMenu(accessor, widget, scopedContextKeyService, { ...attachment, kind: attachment.symbolKind }, MenuId.ChatInputSymbolAttachmentContext))); } await Promise.all(attachmentInitPromises); @@ -1102,12 +1093,12 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge seenEntries.add(attachment.value); } } - for (const [file, state] of chatEditingSession.workingSet.entries()) { - if (!seenEntries.has(file)) { + for (const [file, metadata] of chatEditingSession.workingSet.entries()) { + if (!seenEntries.has(file) && metadata.state !== WorkingSetEntryState.Suggested) { entries.unshift({ reference: file, - state: state.state, - description: state.description, + state: metadata.state, + description: metadata.description, kind: 'reference', }); seenEntries.add(file); @@ -1265,7 +1256,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge if (e.element?.kind === 'reference' && URI.isUri(e.element.reference)) { const modifiedFileUri = e.element.reference; - const entry = chatEditingSession.entries.get().find(entry => entry.modifiedURI.toString() === modifiedFileUri.toString()); + const entry = chatEditingSession.getEntry(modifiedFileUri); const diffInfo = entry?.diffInfo.get(); const range = diffInfo?.changes.at(0)?.modified.toExclusiveRange(); @@ -1299,9 +1290,12 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge const addFilesElement = innerContainer.querySelector('.chat-editing-session-toolbar-actions') as HTMLElement ?? dom.append(innerContainer, $('.chat-editing-session-toolbar-actions')); + const hoverDelegate = getDefaultHoverDelegate('element'); + const button = this._chatEditsActionsDisposables.add(new Button(addFilesElement, { supportIcons: true, - secondary: true + secondary: true, + hoverDelegate })); // Disable the button if the entries that are not suggested exceed the budget button.enabled = remainingFileEntriesBudget > 0; @@ -1311,6 +1305,54 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge this.commandService.executeCommand('workbench.action.chat.editing.attachFiles', { widget: chatWidget }); })); dom.append(addFilesElement, button.element); + + // REALTED files (after Add Files...) + for (const [uri, metadata] of chatEditingSession.workingSet) { + if (metadata.state !== WorkingSetEntryState.Suggested) { + continue; + } + const addBtn = this._chatEditsActionsDisposables.add(new Button(addFilesElement, { + supportIcons: true, + secondary: true, + hoverDelegate + })); + addBtn.enabled = remainingFileEntriesBudget > 0; + addBtn.label = this.labelService.getUriBasenameLabel(uri); + addBtn.element.classList.add('monaco-icon-label', ...getIconClasses(this.modelService, this.languageService, uri, FileKind.FILE)); + addBtn.setTitle(localize('suggeste.title', "{0} - {1}", this.labelService.getUriLabel(uri, { relative: true }), metadata.description ?? '')); + + this._chatEditsActionsDisposables.add(addBtn.onDidClick(() => { + group.remove(); // REMOVE asap + chatEditingSession.addFileToWorkingSet(uri); + })); + + const rmBtn = this._chatEditsActionsDisposables.add(new Button(addFilesElement, { + supportIcons: false, + secondary: true, + hoverDelegate + })); + rmBtn.icon = Codicon.close; + rmBtn.setTitle(localize('chatEditingSession.removeSuggested', 'Remove suggestion')); + this._chatEditsActionsDisposables.add(rmBtn.onDidClick(() => { + group.remove(); // REMOVE asap + chatEditingSession.remove(WorkingSetEntryRemovalReason.User, uri); + })); + + const sep = document.createElement('div'); + sep.classList.add('separator'); + + const group = document.createElement('span'); + group.classList.add('monaco-button-dropdown', 'sidebyside-button'); + group.appendChild(addBtn.element); + group.appendChild(sep); + group.appendChild(rmBtn.element); + dom.append(addFilesElement, group); + + this._chatEditsActionsDisposables.add(toDisposable(() => { + group.remove(); + })); + } + } async renderFollowups(items: IChatFollowup[] | undefined, response: IChatResponseViewModel | undefined): Promise { diff --git a/src/vs/workbench/contrib/chat/browser/chatWidget.ts b/src/vs/workbench/contrib/chat/browser/chatWidget.ts index 8d0be9a14d224..5fcc663e94e1e 100644 --- a/src/vs/workbench/contrib/chat/browser/chatWidget.ts +++ b/src/vs/workbench/contrib/chat/browser/chatWidget.ts @@ -194,7 +194,7 @@ export class ChatWidget extends Disposable implements IChatWidget { return { text: '', parts: [] }; } - this.parsedChatRequest = this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(this.viewModel.sessionId, this.getInput(), this.location, { selectedAgent: this._lastSelectedAgent }); + this.parsedChatRequest = this.instantiationService.createInstance(ChatRequestParser).parseChatRequest(this.viewModel!.sessionId, this.getInput(), this.location, { selectedAgent: this._lastSelectedAgent }); } return this.parsedChatRequest; diff --git a/src/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables.ts b/src/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables.ts index 1e7a4ec971a4b..c1a9eab388134 100644 --- a/src/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables.ts +++ b/src/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables.ts @@ -16,7 +16,6 @@ import { localize } from '../../../../../nls.js'; import { Action2, registerAction2 } from '../../../../../platform/actions/common/actions.js'; import { ICommandService } from '../../../../../platform/commands/common/commands.js'; import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js'; -import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js'; import { ILabelService } from '../../../../../platform/label/common/label.js'; import { ILogService } from '../../../../../platform/log/common/log.js'; import { AnythingQuickAccessProviderRunOptions, IQuickAccessOptions } from '../../../../../platform/quickinput/common/quickAccess.js'; @@ -92,20 +91,13 @@ export class ChatDynamicVariableModel extends Disposable implements IChatWidgetC startColumn: ref.range.startColumn + delta, endLineNumber: ref.range.endLineNumber, endColumn: ref.range.endColumn + delta, - ref.range = { - startLineNumber: ref.range.startLineNumber, - startColumn: ref.range.startColumn + delta, - endLineNumber: ref.range.endLineNumber, - endColumn: ref.range.endColumn + delta, - }; - - return ref; - - return ref; - } + }; return ref; - })); + } + + return ref; + })); }); this.updateDecorations(); @@ -198,11 +190,6 @@ export class ChatDynamicVariableModel extends Disposable implements IChatWidgetC this.disposeVariables(); super.dispose(); } - - public override dispose() { - this.disposeVariables(); - super.dispose(); - } } ChatWidget.CONTRIBS.push(ChatDynamicVariableModel); diff --git a/src/vs/workbench/contrib/chat/browser/contrib/chatImplicitContext.ts b/src/vs/workbench/contrib/chat/browser/contrib/chatImplicitContext.ts index 05dfaf8a35d4f..ed33aec41d9c9 100644 --- a/src/vs/workbench/contrib/chat/browser/contrib/chatImplicitContext.ts +++ b/src/vs/workbench/contrib/chat/browser/contrib/chatImplicitContext.ts @@ -11,7 +11,6 @@ import { URI } from '../../../../../base/common/uri.js'; import { ICodeEditor, isCodeEditor, isDiffEditor } from '../../../../../editor/browser/editorBrowser.js'; import { ICodeEditorService } from '../../../../../editor/browser/services/codeEditorService.js'; import { Location } from '../../../../../editor/common/languages.js'; -import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js'; import { IWorkbenchContribution } from '../../../../common/contributions.js'; import { EditorsOrder } from '../../../../common/editor.js'; import { IEditorService } from '../../../../services/editor/common/editorService.js'; @@ -19,8 +18,6 @@ import { ChatAgentLocation } from '../../common/chatAgents.js'; import { IBaseChatRequestVariableEntry, IChatRequestImplicitVariableEntry } from '../../common/chatModel.js'; import { ILanguageModelIgnoredFilesService } from '../../common/ignoredFiles.js'; import { IChatWidget, IChatWidgetService } from '../chat.js'; -import { PromptFileReference } from '../../common/promptFileReference.js'; -import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js'; export class ChatImplicitContextContribution extends Disposable implements IWorkbenchContribution { static readonly ID = 'chat.implicitContext'; @@ -128,19 +125,6 @@ export class ChatImplicitContextContribution extends Disposable implements IWork } export class ChatImplicitContext extends Disposable implements IChatRequestImplicitVariableEntry { - /** - * Chat reference object for the current implicit context `URI` - * allows to resolve nested file references(aka `prompt snippets`). - */ - private promptFileReference?: PromptFileReference; - - constructor( - @IInstantiationService private readonly instantiationService: IInstantiationService, - @IConfigurationService private readonly configService: IConfigurationService, - ) { - super(); - } - get id() { if (URI.isUri(this.value)) { return 'vscode.implicit.file'; @@ -186,7 +170,7 @@ export class ChatImplicitContext extends Disposable implements IChatRequestImpli return this._isSelection; } - private _onDidChangeValue = this._register(new Emitter()); + private _onDidChangeValue = new Emitter(); readonly onDidChangeValue = this._onDidChangeValue.event; private _value: Location | URI | undefined; @@ -204,72 +188,17 @@ export class ChatImplicitContext extends Disposable implements IChatRequestImpli this._onDidChangeValue.fire(); } - /** - * Get nested file references list, if exists. - */ - public get validFileReferenceUris(): readonly URI[] { - if (!this.promptFileReference) { - return []; - } - - return this.promptFileReference.validFileReferenceUris; + constructor(value?: Location | URI) { + super(); + this._value = value; } - /** - * Set value of the implicit context or remove it if `undefined` is provided. - */ setValue(value: Location | URI | undefined, isSelection: boolean) { - // if the `prompt-snippets` feature is enabled, add a chat reference object - if (PromptFileReference.promptSnippetsEnabled(this.configService)) { - this.addPromptFileReferenceFor(value); - } - this._value = value; this._isSelection = isSelection; this._onDidChangeValue.fire(); } - /** - * Add a prompt file reference object for the provided `URI` value. - */ - private addPromptFileReferenceFor( - value: Location | URI | undefined, - ) { - // new value is `undefined` so remove the existing file reference - if (!value) { - return this.removePromptFileReference(); - } - - // if the `URI` value didn't change and prompt file reference exists, nothing to do - if (this.promptFileReference && this.promptFileReference.sameUri(value)) { - return; - } - - // got a new `URI` value, so remove the existing prompt file - // reference object(if present) and create a new one - this.removePromptFileReference(); - this.promptFileReference = this.instantiationService.createInstance(PromptFileReference, value); - - // subscribe to updates of the prompt file reference - this.promptFileReference.onUpdate( - this._onDidChangeValue.fire.bind(this._onDidChangeValue), - ); - // start resolving the nested prompt file references immediately - this.promptFileReference.resolve(); - } - - /** - * Remove current prompt file reference, if present. - */ - private removePromptFileReference() { - if (!this.promptFileReference) { - return; - } - - this.promptFileReference.dispose(); - delete this.promptFileReference; - } - toBaseEntry(): IBaseChatRequestVariableEntry { return { id: this.id, @@ -280,10 +209,4 @@ export class ChatImplicitContext extends Disposable implements IChatRequestImpli modelDescription: this.modelDescription }; } - - public override dispose() { - this.removePromptFileReference(); - - super.dispose(); - } }