sessions polish

This commit is contained in:
BeniBenj
2026-02-20 00:12:51 +01:00
parent a0ff9d162e
commit 8ff7aae7ab
12 changed files with 334 additions and 60 deletions
@@ -307,7 +307,6 @@ class AccountWidgetContribution extends Disposable implements IWorkbenchContribu
when: ContextKeyExpr.or(
CONTEXT_UPDATE_STATE.isEqualTo(StateType.Ready),
CONTEXT_UPDATE_STATE.isEqualTo(StateType.AvailableForDownload),
CONTEXT_UPDATE_STATE.isEqualTo(StateType.CheckingForUpdates),
CONTEXT_UPDATE_STATE.isEqualTo(StateType.Downloading),
CONTEXT_UPDATE_STATE.isEqualTo(StateType.Downloaded),
CONTEXT_UPDATE_STATE.isEqualTo(StateType.Updating),
@@ -4,13 +4,16 @@
*--------------------------------------------------------------------------------------------*/
import './agentFeedbackEditorInputContribution.js';
import './agentFeedbackGlyphMarginContribution.js';
import './agentFeedbackLineDecorationContribution.js';
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../../workbench/common/contributions.js';
import { AgentFeedbackService, IAgentFeedbackService } from './agentFeedbackService.js';
import { AgentFeedbackAttachmentContribution } from './agentFeedbackAttachment.js';
import { AgentFeedbackAttachmentWidget } from './agentFeedbackAttachmentWidget.js';
import { AgentFeedbackEditorOverlay } from './agentFeedbackEditorOverlay.js';
import { registerAgentFeedbackEditorActions } from './agentFeedbackEditorActions.js';
import { IChatAttachmentWidgetRegistry } from '../../../../workbench/contrib/chat/browser/attachments/chatAttachmentWidgetRegistry.js';
import { IAgentFeedbackVariableEntry } from '../../../../workbench/contrib/chat/common/attachments/chatVariableEntries.js';
registerWorkbenchContribution2(AgentFeedbackEditorOverlay.ID, AgentFeedbackEditorOverlay, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(AgentFeedbackAttachmentContribution.ID, AgentFeedbackAttachmentContribution, WorkbenchPhase.AfterRestored);
@@ -18,3 +21,14 @@ registerWorkbenchContribution2(AgentFeedbackAttachmentContribution.ID, AgentFeed
registerAgentFeedbackEditorActions();
registerSingleton(IAgentFeedbackService, AgentFeedbackService, InstantiationType.Delayed);
// Register the custom attachment widget for agentFeedback attachments
class AgentFeedbackAttachmentWidgetContribution {
static readonly ID = 'workbench.contrib.agentFeedbackAttachmentWidgetFactory';
constructor(@IChatAttachmentWidgetRegistry registry: IChatAttachmentWidgetRegistry) {
registry.registerFactory('agentFeedback', (instantiationService, attachment, options, container) => {
return instantiationService.createInstance(AgentFeedbackAttachmentWidget, attachment as IAgentFeedbackVariableEntry, options, container);
});
}
}
registerWorkbenchContribution2(AgentFeedbackAttachmentWidgetContribution.ID, AgentFeedbackAttachmentWidgetContribution, WorkbenchPhase.AfterRestored);
@@ -14,7 +14,7 @@ import { IAgentFeedbackService, IAgentFeedback } from './agentFeedbackService.js
import { IChatWidgetService } from '../../../../workbench/contrib/chat/browser/chat.js';
import { IAgentFeedbackVariableEntry } from '../../../../workbench/contrib/chat/common/attachments/chatVariableEntries.js';
const ATTACHMENT_ID_PREFIX = 'agentFeedback:';
export const ATTACHMENT_ID_PREFIX = 'agentFeedback:';
/**
* Keeps the "N feedback items" attachment in the chat input in sync with the
@@ -8,7 +8,7 @@ import { Disposable } from '../../../../base/common/lifecycle.js';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from '../../../../editor/browser/editorBrowser.js';
import { IEditorContribution } from '../../../../editor/common/editorCommon.js';
import { EditorContributionInstantiation, registerEditorContribution } from '../../../../editor/browser/editorExtensions.js';
import { GlyphMarginLane, IModelDeltaDecoration, TrackedRangeStickiness } from '../../../../editor/common/model.js';
import { IModelDeltaDecoration, TrackedRangeStickiness } from '../../../../editor/common/model.js';
import { ModelDecorationOptions } from '../../../../editor/common/model/textModel.js';
import { Range } from '../../../../editor/common/core/range.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
@@ -20,19 +20,15 @@ import { IAgentSessionsService } from '../../../../workbench/contrib/chat/browse
import { getSessionForResource } from './agentFeedbackEditorUtils.js';
import { Selection } from '../../../../editor/common/core/selection.js';
const GLYPH_MARGIN_LANE = GlyphMarginLane.Left;
const feedbackGlyphDecoration = ModelDecorationOptions.register({
description: 'agent-feedback-glyph',
glyphMarginClassName: `${ThemeIcon.asClassName(Codicon.comment)} agent-feedback-glyph`,
glyphMargin: { position: GLYPH_MARGIN_LANE },
linesDecorationsClassName: `${ThemeIcon.asClassName(Codicon.comment)} agent-feedback-glyph`,
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
});
const addFeedbackHintDecoration = ModelDecorationOptions.register({
description: 'agent-feedback-add-hint',
glyphMarginClassName: `${ThemeIcon.asClassName(Codicon.add)} agent-feedback-add-hint`,
glyphMargin: { position: GLYPH_MARGIN_LANE },
linesDecorationsClassName: `${ThemeIcon.asClassName(Codicon.add)} agent-feedback-add-hint`,
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
});
@@ -117,9 +113,10 @@ export class AgentFeedbackGlyphMarginContribution extends Disposable implements
return;
}
const isLineDecoration = e.target.type === MouseTargetType.GUTTER_LINE_DECORATIONS && !e.target.detail.isAfterLines;
const isContentArea = e.target.type === MouseTargetType.CONTENT_TEXT || e.target.type === MouseTargetType.CONTENT_EMPTY;
if (e.target.position
&& e.target.type === MouseTargetType.GUTTER_GLYPH_MARGIN
&& !e.target.detail.isAfterLines
&& (isLineDecoration || isContentArea)
&& !this._feedbackLines.has(e.target.position.lineNumber)
) {
this._updateHintDecoration(e.target.position.lineNumber);
@@ -150,7 +147,7 @@ export class AgentFeedbackGlyphMarginContribution extends Disposable implements
private _onMouseDown(e: IEditorMouseEvent): void {
if (!e.target.position
|| e.target.type !== MouseTargetType.GUTTER_GLYPH_MARGIN
|| e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS
|| e.target.detail.isAfterLines
|| !this._sessionResource
) {
@@ -174,9 +171,9 @@ export class AgentFeedbackGlyphMarginContribution extends Disposable implements
const endColumn = model.getLineLastNonWhitespaceColumn(lineNumber);
if (startColumn === 0 || endColumn === 0) {
// Empty line - select the whole line range
this._editor.setSelection(new Selection(lineNumber, 1, lineNumber, model.getLineMaxColumn(lineNumber)));
this._editor.setSelection(new Selection(lineNumber, model.getLineMaxColumn(lineNumber), lineNumber, 1));
} else {
this._editor.setSelection(new Selection(lineNumber, startColumn, lineNumber, endColumn));
this._editor.setSelection(new Selection(lineNumber, endColumn, lineNumber, startColumn));
}
this._editor.focus();
}
@@ -0,0 +1,188 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './media/agentFeedbackLineDecoration.css';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from '../../../../editor/browser/editorBrowser.js';
import { IEditorContribution } from '../../../../editor/common/editorCommon.js';
import { EditorContributionInstantiation, registerEditorContribution } from '../../../../editor/browser/editorExtensions.js';
import { IModelDeltaDecoration, TrackedRangeStickiness } from '../../../../editor/common/model.js';
import { ModelDecorationOptions } from '../../../../editor/common/model/textModel.js';
import { Range } from '../../../../editor/common/core/range.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { URI } from '../../../../base/common/uri.js';
import { IAgentFeedbackService } from './agentFeedbackService.js';
import { IChatEditingService } from '../../../../workbench/contrib/chat/common/editing/chatEditingService.js';
import { IAgentSessionsService } from '../../../../workbench/contrib/chat/browser/agentSessions/agentSessionsService.js';
import { getSessionForResource } from './agentFeedbackEditorUtils.js';
import { Selection } from '../../../../editor/common/core/selection.js';
const feedbackLineDecoration = ModelDecorationOptions.register({
description: 'agent-feedback-line-decoration',
linesDecorationsClassName: `${ThemeIcon.asClassName(Codicon.comment)} agent-feedback-line-decoration`,
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
});
const addFeedbackHintDecoration = ModelDecorationOptions.register({
description: 'agent-feedback-add-hint',
linesDecorationsClassName: `${ThemeIcon.asClassName(Codicon.add)} agent-feedback-add-hint`,
stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
});
export class AgentFeedbackLineDecorationContribution extends Disposable implements IEditorContribution {
static readonly ID = 'agentFeedback.lineDecorationContribution';
private readonly _feedbackDecorations;
private _hintDecorationId: string | null = null;
private _hintLine = -1;
private _sessionResource: URI | undefined;
private _feedbackLines = new Set<number>();
constructor(
private readonly _editor: ICodeEditor,
@IAgentFeedbackService private readonly _agentFeedbackService: IAgentFeedbackService,
@IChatEditingService private readonly _chatEditingService: IChatEditingService,
@IAgentSessionsService private readonly _agentSessionsService: IAgentSessionsService,
) {
super();
this._feedbackDecorations = this._editor.createDecorationsCollection();
this._store.add(this._agentFeedbackService.onDidChangeFeedback(() => this._updateFeedbackDecorations()));
this._store.add(this._editor.onDidChangeModel(() => this._onModelChanged()));
this._store.add(this._editor.onMouseMove((e: IEditorMouseEvent) => this._onMouseMove(e)));
this._store.add(this._editor.onMouseLeave(() => this._updateHintDecoration(-1)));
this._store.add(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onMouseDown(e)));
this._resolveSession();
this._updateFeedbackDecorations();
}
private _onModelChanged(): void {
this._updateHintDecoration(-1);
this._resolveSession();
this._updateFeedbackDecorations();
}
private _resolveSession(): void {
const model = this._editor.getModel();
if (!model) {
this._sessionResource = undefined;
return;
}
this._sessionResource = getSessionForResource(model.uri, this._chatEditingService, this._agentSessionsService);
}
private _updateFeedbackDecorations(): void {
if (!this._sessionResource) {
this._feedbackDecorations.clear();
this._feedbackLines.clear();
return;
}
const feedbackItems = this._agentFeedbackService.getFeedback(this._sessionResource);
const decorations: IModelDeltaDecoration[] = [];
const lines = new Set<number>();
for (const item of feedbackItems) {
const model = this._editor.getModel();
if (!model || item.resourceUri.toString() !== model.uri.toString()) {
continue;
}
const line = item.range.startLineNumber;
lines.add(line);
decorations.push({
range: new Range(line, 1, line, 1),
options: feedbackLineDecoration,
});
}
this._feedbackLines = lines;
this._feedbackDecorations.set(decorations);
}
private _onMouseMove(e: IEditorMouseEvent): void {
if (!this._sessionResource) {
this._updateHintDecoration(-1);
return;
}
const isLineDecoration = e.target.type === MouseTargetType.GUTTER_LINE_DECORATIONS && !e.target.detail.isAfterLines;
const isContentArea = e.target.type === MouseTargetType.CONTENT_TEXT || e.target.type === MouseTargetType.CONTENT_EMPTY;
if (e.target.position
&& (isLineDecoration || isContentArea)
&& !this._feedbackLines.has(e.target.position.lineNumber)
) {
this._updateHintDecoration(e.target.position.lineNumber);
} else {
this._updateHintDecoration(-1);
}
}
private _updateHintDecoration(line: number): void {
if (line === this._hintLine) {
return;
}
this._hintLine = line;
this._editor.changeDecorations(accessor => {
if (this._hintDecorationId) {
accessor.removeDecoration(this._hintDecorationId);
this._hintDecorationId = null;
}
if (line !== -1) {
this._hintDecorationId = accessor.addDecoration(
new Range(line, 1, line, 1),
addFeedbackHintDecoration,
);
}
});
}
private _onMouseDown(e: IEditorMouseEvent): void {
if (!e.target.position
|| e.target.type !== MouseTargetType.GUTTER_LINE_DECORATIONS
|| e.target.detail.isAfterLines
|| !this._sessionResource
) {
return;
}
const lineNumber = e.target.position.lineNumber;
// Lines with existing feedback - do nothing
if (this._feedbackLines.has(lineNumber)) {
return;
}
// Select the line content and focus the editor
const model = this._editor.getModel();
if (!model) {
return;
}
const startColumn = model.getLineFirstNonWhitespaceColumn(lineNumber);
const endColumn = model.getLineLastNonWhitespaceColumn(lineNumber);
if (startColumn === 0 || endColumn === 0) {
// Empty line - select the whole line range
this._editor.setSelection(new Selection(lineNumber, model.getLineMaxColumn(lineNumber), lineNumber, 1));
} else {
this._editor.setSelection(new Selection(lineNumber, endColumn, lineNumber, startColumn));
}
this._editor.focus();
}
override dispose(): void {
this._feedbackDecorations.clear();
this._updateHintDecoration(-1);
super.dispose();
}
}
registerEditorContribution(AgentFeedbackLineDecorationContribution.ID, AgentFeedbackLineDecorationContribution, EditorContributionInstantiation.Eventually);
@@ -13,7 +13,6 @@ import { isEqual } from '../../../../base/common/resources.js';
import { IChatEditingService } from '../../../../workbench/contrib/chat/common/editing/chatEditingService.js';
import { IAgentSessionsService } from '../../../../workbench/contrib/chat/browser/agentSessions/agentSessionsService.js';
import { agentSessionContainsResource, editingEntriesContainResource } from '../../../../workbench/contrib/chat/browser/sessionResourceMatching.js';
import { IChatWidget, IChatWidgetService } from '../../../../workbench/contrib/chat/browser/chat.js';
// --- Types --------------------------------------------------------------------
@@ -83,8 +82,6 @@ export interface IAgentFeedbackService {
// --- Implementation -----------------------------------------------------------
const AGENT_FEEDBACK_ATTACHMENT_ID_PREFIX = 'agentFeedback:';
export class AgentFeedbackService extends Disposable implements IAgentFeedbackService {
declare readonly _serviceBrand: undefined;
@@ -103,41 +100,8 @@ export class AgentFeedbackService extends Disposable implements IAgentFeedbackSe
constructor(
@IChatEditingService private readonly _chatEditingService: IChatEditingService,
@IAgentSessionsService private readonly _agentSessionsService: IAgentSessionsService,
@IChatWidgetService private readonly _chatWidgetService: IChatWidgetService,
) {
super();
this._registerChatWidgetListeners();
}
private _registerChatWidgetListeners(): void {
for (const widget of this._chatWidgetService.getAllWidgets()) {
this._registerWidgetListeners(widget);
}
this._store.add(this._chatWidgetService.onDidAddWidget(widget => {
this._registerWidgetListeners(widget);
}));
}
private _registerWidgetListeners(widget: IChatWidget): void {
this._store.add(widget.attachmentModel.onDidChange(e => {
for (const deletedId of e.deleted) {
if (!deletedId.startsWith(AGENT_FEEDBACK_ATTACHMENT_ID_PREFIX)) {
continue;
}
const sessionResourceString = deletedId.slice(AGENT_FEEDBACK_ATTACHMENT_ID_PREFIX.length);
if (!sessionResourceString) {
continue;
}
const sessionResource = URI.parse(sessionResourceString);
if (this.getFeedback(sessionResource).length > 0) {
this.clearFeedback(sessionResource);
}
}
}));
}
addFeedback(sessionResource: URI, resourceUri: URI, range: IRange, text: string): IAgentFeedback {
@@ -3,24 +3,23 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .glyph-margin-widgets .cgmr.agent-feedback-glyph,
.monaco-editor .glyph-margin-widgets .cgmr.agent-feedback-add-hint {
.monaco-editor .agent-feedback-glyph,
.monaco-editor .agent-feedback-add-hint {
border-radius: 3px;
display: flex !important;
align-items: center;
justify-content: center;
}
.monaco-editor .glyph-margin-widgets .cgmr.agent-feedback-glyph {
background-color: var(--vscode-editorGutter-commentGlyphForeground, var(--vscode-icon-foreground));
color: var(--vscode-editor-background);
.monaco-editor .agent-feedback-glyph {
background-color: var(--vscode-toolbar-hoverBackground);
}
.monaco-editor .glyph-margin-widgets .cgmr.agent-feedback-add-hint {
.monaco-editor .agent-feedback-add-hint {
background-color: var(--vscode-toolbar-hoverBackground);
opacity: 0.7;
}
.monaco-editor .glyph-margin-widgets .cgmr.agent-feedback-add-hint:hover {
.monaco-editor .agent-feedback-add-hint:hover {
opacity: 1;
}
@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-editor .agent-feedback-line-decoration,
.monaco-editor .agent-feedback-add-hint {
border-radius: 3px;
display: flex !important;
align-items: center;
justify-content: center;
}
.monaco-editor .agent-feedback-line-decoration {
background-color: var(--vscode-toolbar-hoverBackground);
}
.monaco-editor .agent-feedback-add-hint {
background-color: var(--vscode-toolbar-hoverBackground);
opacity: 0.7;
}
.monaco-editor .agent-feedback-add-hint:hover {
opacity: 1;
}
@@ -124,10 +124,11 @@
.ai-customization-toolbar .ai-customization-toolbar-content {
max-height: 500px;
overflow: hidden;
transition: max-height 0.2s ease-out;
transition: max-height 0.2s ease-out, display 0s linear 0.2s;
}
.ai-customization-toolbar.collapsed .ai-customization-toolbar-content {
max-height: 0;
display: none;
}
}
@@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as event from '../../../../../base/common/event.js';
import { IDisposable } from '../../../../../base/common/lifecycle.js';
import { createDecorator, IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IChatRequestVariableEntry } from '../../common/attachments/chatVariableEntries.js';
/**
* Interface for a contributed attachment widget instance.
*/
export interface IChatAttachmentWidgetInstance extends IDisposable {
readonly element: HTMLElement;
readonly onDidDelete: event.Event<Event>;
readonly onDidOpen: event.Event<void>;
}
/**
* Factory function type for creating attachment widgets.
* Receives the instantiation service so it can create DI-injected widget instances.
*/
export type ChatAttachmentWidgetFactory = (
instantiationService: IInstantiationService,
attachment: IChatRequestVariableEntry,
options: { shouldFocusClearButton: boolean; supportsDeletion: boolean },
container: HTMLElement,
) => IChatAttachmentWidgetInstance;
export const IChatAttachmentWidgetRegistry = createDecorator<IChatAttachmentWidgetRegistry>('chatAttachmentWidgetRegistry');
export interface IChatAttachmentWidgetRegistry {
readonly _serviceBrand: undefined;
/**
* Register a widget factory for a specific attachment kind.
*/
registerFactory(kind: string, factory: ChatAttachmentWidgetFactory): IDisposable;
/**
* Try to create a widget for the given attachment using a registered factory.
* Returns undefined if no factory is registered for the attachment's kind.
*/
createWidget(
instantiationService: IInstantiationService,
attachment: IChatRequestVariableEntry,
options: { shouldFocusClearButton: boolean; supportsDeletion: boolean },
container: HTMLElement,
): IChatAttachmentWidgetInstance | undefined;
}
export class ChatAttachmentWidgetRegistry implements IChatAttachmentWidgetRegistry {
declare readonly _serviceBrand: undefined;
private readonly _factories = new Map<string, ChatAttachmentWidgetFactory>();
registerFactory(kind: string, factory: ChatAttachmentWidgetFactory): IDisposable {
this._factories.set(kind, factory);
return {
dispose: () => {
if (this._factories.get(kind) === factory) {
this._factories.delete(kind);
}
}
};
}
createWidget(
instantiationService: IInstantiationService,
attachment: IChatRequestVariableEntry,
options: { shouldFocusClearButton: boolean; supportsDeletion: boolean },
container: HTMLElement,
): IChatAttachmentWidgetInstance | undefined {
const factory = this._factories.get(attachment.kind);
if (!factory) {
return undefined;
}
return factory(instantiationService, attachment, options, container);
}
}
@@ -96,6 +96,7 @@ import { ChatAccessibilityService } from './accessibility/chatAccessibilityServi
import './attachments/chatAttachmentModel.js';
import './widget/input/chatStatusWidget.js';
import { ChatAttachmentResolveService, IChatAttachmentResolveService } from './attachments/chatAttachmentResolveService.js';
import { ChatAttachmentWidgetRegistry, IChatAttachmentWidgetRegistry } from './attachments/chatAttachmentWidgetRegistry.js';
import { ChatMarkdownAnchorService, IChatMarkdownAnchorService } from './widget/chatContentParts/chatMarkdownAnchorService.js';
import { ChatContextPickService, IChatContextPickService } from './attachments/chatContextPickService.js';
import { ChatInputBoxContentProvider } from './widget/input/editor/chatEditorInputContentProvider.js';
@@ -1542,6 +1543,7 @@ registerSingleton(IPromptsService, PromptsService, InstantiationType.Delayed);
registerSingleton(IChatContextPickService, ChatContextPickService, InstantiationType.Delayed);
registerSingleton(IChatModeService, ChatModeService, InstantiationType.Delayed);
registerSingleton(IChatAttachmentResolveService, ChatAttachmentResolveService, InstantiationType.Delayed);
registerSingleton(IChatAttachmentWidgetRegistry, ChatAttachmentWidgetRegistry, InstantiationType.Delayed);
registerSingleton(IChatTodoListService, ChatTodoListService, InstantiationType.Delayed);
registerSingleton(IChatOutputRendererService, ChatOutputRendererService, InstantiationType.Delayed);
registerSingleton(IChatLayoutService, ChatLayoutService, InstantiationType.Delayed);
@@ -100,6 +100,7 @@ import { ChatSessionPrimaryPickerAction, ChatSubmitAction, IChatExecuteActionCon
import { AgentSessionProviders, getAgentSessionProvider } from '../../agentSessions/agentSessions.js';
import { IAgentSessionsService } from '../../agentSessions/agentSessionsService.js';
import { ChatAttachmentModel } from '../../attachments/chatAttachmentModel.js';
import { IChatAttachmentWidgetRegistry } from '../../attachments/chatAttachmentWidgetRegistry.js';
import { DefaultChatAttachmentWidget, ElementChatAttachmentWidget, FileAttachmentWidget, ImageAttachmentWidget, NotebookCellOutputChatAttachmentWidget, PasteAttachmentWidget, PromptFileAttachmentWidget, PromptTextAttachmentWidget, SCMHistoryItemAttachmentWidget, SCMHistoryItemChangeAttachmentWidget, SCMHistoryItemChangeRangeAttachmentWidget, TerminalCommandAttachmentWidget, ToolSetOrToolItemAttachmentWidget } from '../../attachments/chatAttachmentWidgets.js';
import { ChatImplicitContexts } from '../../attachments/chatImplicitContext.js';
import { ImplicitContextAttachmentWidget } from '../../attachments/implicitContextAttachment.js';
@@ -512,6 +513,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IChatAttachmentWidgetRegistry private readonly _chatAttachmentWidgetRegistry: IChatAttachmentWidgetRegistry,
) {
super();
@@ -2439,7 +2441,8 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
} else if (isSCMHistoryItemChangeRangeVariableEntry(attachment)) {
attachmentWidget = this.instantiationService.createInstance(SCMHistoryItemChangeRangeAttachmentWidget, attachment, lm, options, container, this._contextResourceLabels);
} else {
attachmentWidget = this.instantiationService.createInstance(DefaultChatAttachmentWidget, resource, range, attachment, undefined, lm, options, container, this._contextResourceLabels);
attachmentWidget = this._chatAttachmentWidgetRegistry.createWidget(this.instantiationService, attachment, options, container)
?? this.instantiationService.createInstance(DefaultChatAttachmentWidget, resource, range, attachment, undefined, lm, options, container, this._contextResourceLabels);
}
if (shouldFocusClearButton) {