Merge pull request #296139 from microsoft/benibenj/lazy-tarsier

Agent sessions feedback for sessions window
This commit is contained in:
Benjamin Christopher Simmonds
2026-02-19 01:12:43 +01:00
committed by GitHub
18 changed files with 508 additions and 122 deletions

View File

@@ -245,7 +245,6 @@ export class MenuId {
static readonly MergeInputResultToolbar = new MenuId('MergeToolbarResultToolbar');
static readonly InlineSuggestionToolbar = new MenuId('InlineSuggestionToolbar');
static readonly InlineEditToolbar = new MenuId('InlineEditToolbar');
static readonly AgentFeedbackEditorContent = new MenuId('AgentFeedbackEditorContent');
static readonly ChatContext = new MenuId('ChatContext');
static readonly ChatCodeBlock = new MenuId('ChatCodeblock');
static readonly ChatCompareBlock = new MenuId('ChatCompareBlock');

View File

@@ -24,4 +24,5 @@ export const Menus = {
AuxiliaryBarTitleLeft: new MenuId('SessionsAuxiliaryBarTitleLeft'),
SidebarFooter: new MenuId('SessionsSidebarFooter'),
SidebarCustomizations: new MenuId('SessionsSidebarCustomizations'),
AgentFeedbackEditorContent: new MenuId('AgentFeedbackEditorContent'),
} as const;

View File

@@ -0,0 +1,19 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './agentFeedbackEditorInputContribution.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 { AgentFeedbackEditorOverlay } from './agentFeedbackEditorOverlay.js';
import { registerAgentFeedbackEditorActions } from './agentFeedbackEditorActions.js';
registerWorkbenchContribution2(AgentFeedbackEditorOverlay.ID, AgentFeedbackEditorOverlay, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(AgentFeedbackAttachmentContribution.ID, AgentFeedbackAttachmentContribution, WorkbenchPhase.AfterRestored);
registerAgentFeedbackEditorActions();
registerSingleton(IAgentFeedbackService, AgentFeedbackService, InstantiationType.Delayed);

View File

@@ -3,16 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable, DisposableMap } from '../../../../../base/common/lifecycle.js';
import { Codicon } from '../../../../../base/common/codicons.js';
import { basename } from '../../../../../base/common/resources.js';
import { URI } from '../../../../../base/common/uri.js';
import { IRange } from '../../../../../editor/common/core/range.js';
import { ITextModelService } from '../../../../../editor/common/services/resolverService.js';
import { localize } from '../../../../../nls.js';
import { Disposable, DisposableMap } from '../../../../base/common/lifecycle.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { basename } from '../../../../base/common/resources.js';
import { URI } from '../../../../base/common/uri.js';
import { IRange } from '../../../../editor/common/core/range.js';
import { ITextModelService } from '../../../../editor/common/services/resolverService.js';
import { localize } from '../../../../nls.js';
import { IAgentFeedbackService, IAgentFeedback } from './agentFeedbackService.js';
import { IChatWidgetService } from '../chat.js';
import { IAgentFeedbackVariableEntry } from '../../common/attachments/chatVariableEntries.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:';

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import './media/agentFeedbackAttachment.css';
import * as dom from '../../../../../base/browser/dom.js';
import { Codicon } from '../../../../../base/common/codicons.js';
import { ThemeIcon } from '../../../../../base/common/themables.js';
import { Disposable } from '../../../../../base/common/lifecycle.js';
import * as event from '../../../../../base/common/event.js';
import { localize } from '../../../../../nls.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IAgentFeedbackVariableEntry } from '../../common/attachments/chatVariableEntries.js';
import * as dom from '../../../../base/browser/dom.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import * as event from '../../../../base/common/event.js';
import { localize } from '../../../../nls.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IAgentFeedbackVariableEntry } from '../../../../workbench/contrib/chat/common/attachments/chatVariableEntries.js';
import { AgentFeedbackHover } from './agentFeedbackHover.js';
/**

View File

@@ -3,20 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Codicon } from '../../../../../base/common/codicons.js';
import { localize, localize2 } from '../../../../../nls.js';
import { Action2, MenuId, MenuRegistry, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
import { URI } from '../../../../../base/common/uri.js';
import { isEqual } from '../../../../../base/common/resources.js';
import { EditorsOrder, IEditorIdentifier } from '../../../../common/editor.js';
import { IEditorService } from '../../../../services/editor/common/editorService.js';
import { IChatWidgetService } from '../chat.js';
import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';
import { CHAT_CATEGORY } from '../actions/chatActions.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { localize, localize2 } from '../../../../nls.js';
import { Action2, MenuRegistry, registerAction2 } from '../../../../platform/actions/common/actions.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
import { URI } from '../../../../base/common/uri.js';
import { isEqual } from '../../../../base/common/resources.js';
import { EditorsOrder, IEditorIdentifier } from '../../../../workbench/common/editor.js';
import { IEditorService } from '../../../../workbench/services/editor/common/editorService.js';
import { IChatWidgetService } from '../../../../workbench/contrib/chat/browser/chat.js';
import { ChatContextKeys } from '../../../../workbench/contrib/chat/common/actions/chatContextKeys.js';
import { CHAT_CATEGORY } from '../../../../workbench/contrib/chat/browser/actions/chatActions.js';
import { IAgentFeedbackService } from './agentFeedbackService.js';
import { getActiveResourceCandidates } from './agentFeedbackEditorUtils.js';
import { Menus } from '../../../browser/menus.js';
export const submitFeedbackActionId = 'agentFeedbackEditor.action.submit';
export const navigatePreviousFeedbackActionId = 'agentFeedbackEditor.action.navigatePrevious';
@@ -61,7 +62,7 @@ class SubmitFeedbackAction extends AgentFeedbackEditorAction {
icon: Codicon.send,
precondition: ChatContextKeys.enabled,
menu: {
id: MenuId.AgentFeedbackEditorContent,
id: Menus.AgentFeedbackEditorContent,
group: 'a_submit',
order: 0,
when: ChatContextKeys.enabled,
@@ -110,7 +111,7 @@ class NavigateFeedbackAction extends AgentFeedbackEditorAction {
f1: true,
precondition: ChatContextKeys.enabled,
menu: {
id: MenuId.AgentFeedbackEditorContent,
id: Menus.AgentFeedbackEditorContent,
group: 'navigate',
order: _next ? 2 : 1,
when: ChatContextKeys.enabled,
@@ -149,7 +150,7 @@ class ClearAllFeedbackAction extends AgentFeedbackEditorAction {
f1: true,
precondition: ContextKeyExpr.and(ChatContextKeys.enabled),
menu: {
id: MenuId.AgentFeedbackEditorContent,
id: Menus.AgentFeedbackEditorContent,
group: 'a_submit',
order: 1,
when: ChatContextKeys.enabled,
@@ -169,7 +170,7 @@ export function registerAgentFeedbackEditorActions(): void {
registerAction2(class extends NavigateFeedbackAction { constructor() { super(true); } });
registerAction2(ClearAllFeedbackAction);
MenuRegistry.appendMenuItem(MenuId.AgentFeedbackEditorContent, {
MenuRegistry.appendMenuItem(Menus.AgentFeedbackEditorContent, {
command: {
id: navigationBearingFakeActionId,
title: localize('label', 'Navigation Status'),

View File

@@ -0,0 +1,308 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import './media/agentFeedbackEditorInput.css';
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition } from '../../../../editor/browser/editorBrowser.js';
import { IEditorContribution } from '../../../../editor/common/editorCommon.js';
import { EditorContributionInstantiation, registerEditorContribution } from '../../../../editor/browser/editorExtensions.js';
import { EditorOption } from '../../../../editor/common/config/editorOptions.js';
import { SelectionDirection } from '../../../../editor/common/core/selection.js';
import { URI } from '../../../../base/common/uri.js';
import { addStandardDisposableListener, getWindow } from '../../../../base/browser/dom.js';
import { KeyCode } from '../../../../base/common/keyCodes.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 { localize } from '../../../../nls.js';
class AgentFeedbackInputWidget implements IOverlayWidget {
private static readonly _ID = 'agentFeedback.inputWidget';
readonly allowEditorOverflow = false;
private readonly _domNode: HTMLElement;
private readonly _inputElement: HTMLInputElement;
private _position: IOverlayWidgetPosition | null = null;
constructor(
private readonly _editor: ICodeEditor,
) {
this._domNode = document.createElement('div');
this._domNode.classList.add('agent-feedback-input-widget');
this._domNode.style.display = 'none';
this._inputElement = document.createElement('input');
this._inputElement.type = 'text';
this._inputElement.placeholder = localize('agentFeedback.addFeedback', "Add Feedback");
this._domNode.appendChild(this._inputElement);
this._editor.applyFontInfo(this._inputElement);
}
getId(): string {
return AgentFeedbackInputWidget._ID;
}
getDomNode(): HTMLElement {
return this._domNode;
}
getPosition(): IOverlayWidgetPosition | null {
return this._position;
}
get inputElement(): HTMLInputElement {
return this._inputElement;
}
setPosition(position: IOverlayWidgetPosition | null): void {
this._position = position;
this._editor.layoutOverlayWidget(this);
}
show(): void {
this._domNode.style.display = '';
}
hide(): void {
this._domNode.style.display = 'none';
}
clearInput(): void {
this._inputElement.value = '';
}
}
export class AgentFeedbackEditorInputContribution extends Disposable implements IEditorContribution {
static readonly ID = 'agentFeedback.editorInputContribution';
private _widget: AgentFeedbackInputWidget | undefined;
private _visible = false;
private _mouseDown = false;
private _sessionResource: URI | undefined;
private readonly _widgetListeners = this._store.add(new DisposableStore());
constructor(
private readonly _editor: ICodeEditor,
@IAgentFeedbackService private readonly _agentFeedbackService: IAgentFeedbackService,
@IChatEditingService private readonly _chatEditingService: IChatEditingService,
@IAgentSessionsService private readonly _agentSessionsService: IAgentSessionsService,
) {
super();
this._store.add(this._editor.onDidChangeCursorSelection(() => this._onSelectionChanged()));
this._store.add(this._editor.onDidChangeModel(() => this._onModelChanged()));
this._store.add(this._editor.onDidScrollChange(() => {
if (this._visible) {
this._updatePosition();
}
}));
this._store.add(this._editor.onMouseDown(() => {
this._mouseDown = true;
this._hide();
}));
this._store.add(this._editor.onMouseUp(() => {
this._mouseDown = false;
this._onSelectionChanged();
}));
this._store.add(this._editor.onDidBlurEditorWidget(() => this._hide()));
this._store.add(this._editor.onDidFocusEditorWidget(() => this._onSelectionChanged()));
}
private _ensureWidget(): AgentFeedbackInputWidget {
if (!this._widget) {
this._widget = new AgentFeedbackInputWidget(this._editor);
this._editor.addOverlayWidget(this._widget);
}
return this._widget;
}
private _onModelChanged(): void {
this._hide();
this._sessionResource = undefined;
}
private _onSelectionChanged(): void {
if (this._mouseDown || !this._editor.hasWidgetFocus()) {
return;
}
const selection = this._editor.getSelection();
if (!selection || selection.isEmpty()) {
this._hide();
return;
}
const model = this._editor.getModel();
if (!model) {
this._hide();
return;
}
const match = getSessionForResource(model.uri, this._chatEditingService, this._agentSessionsService);
if (!match) {
this._hide();
return;
}
this._sessionResource = match.sessionResource;
this._show();
}
private _show(): void {
const widget = this._ensureWidget();
if (!this._visible) {
this._visible = true;
this._registerWidgetListeners(widget);
}
widget.clearInput();
widget.show();
this._updatePosition();
}
private _hide(): void {
if (!this._visible) {
return;
}
this._visible = false;
this._widgetListeners.clear();
if (this._widget) {
this._widget.hide();
this._widget.setPosition(null);
this._widget.clearInput();
}
}
private _registerWidgetListeners(widget: AgentFeedbackInputWidget): void {
this._widgetListeners.clear();
// Listen for keydown on the editor dom node to detect when the user starts typing
const editorDomNode = this._editor.getDomNode();
if (editorDomNode) {
this._widgetListeners.add(addStandardDisposableListener(editorDomNode, 'keydown', e => {
if (!this._visible) {
return;
}
// Don't focus if a modifier key is pressed alone
if (e.keyCode === KeyCode.Ctrl || e.keyCode === KeyCode.Shift || e.keyCode === KeyCode.Alt || e.keyCode === KeyCode.Meta) {
return;
}
// Don't focus if any modifier is held (keyboard shortcuts)
if (e.ctrlKey || e.altKey || e.metaKey) {
return;
}
// Don't capture Escape at this level - let it fall through to the input handler if focused
if (e.keyCode === KeyCode.Escape) {
this._hide();
this._editor.focus();
return;
}
// If the input is not focused, focus it and let the keystroke go through
if (getWindow(widget.inputElement).document.activeElement !== widget.inputElement) {
widget.inputElement.focus();
}
}));
}
// Listen for keydown on the input element
this._widgetListeners.add(addStandardDisposableListener(widget.inputElement, 'keydown', e => {
if (e.keyCode === KeyCode.Escape) {
e.preventDefault();
e.stopPropagation();
this._hide();
this._editor.focus();
return;
}
if (e.keyCode === KeyCode.Enter) {
e.preventDefault();
e.stopPropagation();
this._submit(widget);
return;
}
}));
// Stop propagation of input events so the editor doesn't handle them
this._widgetListeners.add(addStandardDisposableListener(widget.inputElement, 'keypress', e => {
e.stopPropagation();
}));
}
private _submit(widget: AgentFeedbackInputWidget): void {
const text = widget.inputElement.value.trim();
if (!text) {
return;
}
const selection = this._editor.getSelection();
const model = this._editor.getModel();
if (!selection || !model || !this._sessionResource) {
return;
}
this._agentFeedbackService.addFeedback(this._sessionResource, model.uri, selection, text);
this._hide();
this._editor.focus();
}
private _updatePosition(): void {
if (!this._widget || !this._visible) {
return;
}
const selection = this._editor.getSelection();
if (!selection || selection.isEmpty()) {
this._hide();
return;
}
const cursorPosition = selection.getDirection() === SelectionDirection.LTR
? selection.getEndPosition()
: selection.getStartPosition();
const scrolledPosition = this._editor.getScrolledVisiblePosition(cursorPosition);
if (!scrolledPosition) {
this._widget.setPosition(null);
return;
}
const lineHeight = this._editor.getOption(EditorOption.lineHeight);
const left = scrolledPosition.left;
let top: number;
if (selection.getDirection() === SelectionDirection.LTR) {
// Cursor at end (bottom) of selection → place widget below the cursor line
top = scrolledPosition.top + lineHeight;
} else {
// Cursor at start (top) of selection → place widget above the cursor line
const widgetHeight = this._widget.getDomNode().offsetHeight || 30;
top = scrolledPosition.top - widgetHeight;
}
this._widget.setPosition({ preference: { top, left } });
}
override dispose(): void {
if (this._widget) {
this._editor.removeOverlayWidget(this._widget);
this._widget = undefined;
}
super.dispose();
}
}
registerEditorContribution(AgentFeedbackEditorInputContribution.ID, AgentFeedbackEditorInputContribution, EditorContributionInstantiation.Eventually);

View File

@@ -4,25 +4,25 @@
*--------------------------------------------------------------------------------------------*/
import './media/agentFeedbackEditorOverlay.css';
import { Disposable, DisposableMap, DisposableStore, combinedDisposable, toDisposable } from '../../../../../base/common/lifecycle.js';
import { autorun, observableFromEvent, observableSignalFromEvent, observableValue } from '../../../../../base/common/observable.js';
import { ActionViewItem, IBaseActionViewItemOptions } from '../../../../../base/browser/ui/actionbar/actionViewItems.js';
import { IAction } from '../../../../../base/common/actions.js';
import { Event } from '../../../../../base/common/event.js';
import { HiddenItemStrategy, MenuWorkbenchToolBar } from '../../../../../platform/actions/browser/toolbar.js';
import { MenuId } from '../../../../../platform/actions/common/actions.js';
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.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 { IWorkbenchContribution } from '../../../../common/contributions.js';
import { EditorGroupView } from '../../../../browser/parts/editor/editorGroupView.js';
import { IEditorGroup, IEditorGroupsService } from '../../../../services/editor/common/editorGroupsService.js';
import { Disposable, DisposableMap, DisposableStore, combinedDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { autorun, observableFromEvent, observableSignalFromEvent, observableValue } from '../../../../base/common/observable.js';
import { ActionViewItem, IBaseActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
import { IAction } from '../../../../base/common/actions.js';
import { Event } from '../../../../base/common/event.js';
import { HiddenItemStrategy, MenuWorkbenchToolBar } from '../../../../platform/actions/browser/toolbar.js';
import { IContextKeyService } from '../../../../platform/contextkey/common/contextkey.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 { IWorkbenchContribution } from '../../../../workbench/common/contributions.js';
import { EditorGroupView } from '../../../../workbench/browser/parts/editor/editorGroupView.js';
import { IEditorGroup, IEditorGroupsService } from '../../../../workbench/services/editor/common/editorGroupsService.js';
import { IAgentFeedbackService } from './agentFeedbackService.js';
import { navigateNextFeedbackActionId, navigatePreviousFeedbackActionId, navigationBearingFakeActionId, submitFeedbackActionId } from './agentFeedbackEditorActions.js';
import { assertType } from '../../../../../base/common/types.js';
import { localize } from '../../../../../nls.js';
import { assertType } from '../../../../base/common/types.js';
import { localize } from '../../../../nls.js';
import { getActiveResourceCandidates } from './agentFeedbackEditorUtils.js';
import { Menus } from '../../../browser/menus.js';
class AgentFeedbackActionViewItem extends ActionViewItem {
@@ -84,7 +84,7 @@ class AgentFeedbackOverlayWidget extends Disposable {
this._domNode.appendChild(this._toolbarNode);
}
this._showStore.add(this._instaService.createInstance(MenuWorkbenchToolBar, this._toolbarNode, MenuId.AgentFeedbackEditorContent, {
this._showStore.add(this._instaService.createInstance(MenuWorkbenchToolBar, this._toolbarNode, Menus.AgentFeedbackEditorContent, {
telemetrySource: 'agentFeedback.overlayToolbar',
hiddenItemStrategy: HiddenItemStrategy.Ignore,
toolbarOptions: {

View File

@@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------------------------
* 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 { EditorResourceAccessor, SideBySideEditor } from '../../../../workbench/common/editor.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';
export interface ISessionResourceMatch {
readonly sessionResource: URI;
readonly resourceUri: URI;
}
/**
* Find the session that contains the given resource by checking editing sessions and agent sessions.
*/
export function getSessionForResource(
resourceUri: URI,
chatEditingService: IChatEditingService,
agentSessionsService: IAgentSessionsService,
): ISessionResourceMatch | undefined {
for (const editingSession of chatEditingService.editingSessionsObs.get()) {
if (editingEntriesContainResource(editingSession.entries.get(), resourceUri)) {
return { sessionResource: editingSession.chatSessionResource, resourceUri };
}
}
for (const session of agentSessionsService.model.sessions) {
if (agentSessionContainsResource(session, resourceUri)) {
return { sessionResource: session.resource, resourceUri };
}
}
return undefined;
}
export function getActiveResourceCandidates(input: Parameters<typeof EditorResourceAccessor.getOriginalUri>[0]): URI[] {
const result: URI[] = [];
const resources = EditorResourceAccessor.getOriginalUri(input, { supportSideBySide: SideBySideEditor.BOTH });
if (!resources) {
return result;
}
if (URI.isUri(resources)) {
result.push(resources);
return result;
}
if (resources.secondary) {
result.push(resources.secondary);
}
if (resources.primary) {
result.push(resources.primary);
}
return result;
}

View File

@@ -3,21 +3,21 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as dom from '../../../../../base/browser/dom.js';
import { HoverStyle } from '../../../../../base/browser/ui/hover/hover.js';
import { HoverPosition } from '../../../../../base/browser/ui/hover/hoverWidget.js';
import { Codicon } from '../../../../../base/common/codicons.js';
import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
import { ThemeIcon } from '../../../../../base/common/themables.js';
import { IRange } from '../../../../../editor/common/core/range.js';
import { URI } from '../../../../../base/common/uri.js';
import { localize } from '../../../../../nls.js';
import { IHoverService } from '../../../../../platform/hover/browser/hover.js';
import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
import { IEditorService } from '../../../../services/editor/common/editorService.js';
import { DEFAULT_LABELS_CONTAINER, ResourceLabels } from '../../../../browser/labels.js';
import * as dom from '../../../../base/browser/dom.js';
import { HoverStyle } from '../../../../base/browser/ui/hover/hover.js';
import { HoverPosition } from '../../../../base/browser/ui/hover/hoverWidget.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
import { ThemeIcon } from '../../../../base/common/themables.js';
import { IRange } from '../../../../editor/common/core/range.js';
import { URI } from '../../../../base/common/uri.js';
import { localize } from '../../../../nls.js';
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { IEditorService } from '../../../../workbench/services/editor/common/editorService.js';
import { DEFAULT_LABELS_CONTAINER, ResourceLabels } from '../../../../workbench/browser/labels.js';
import { IAgentFeedbackService } from './agentFeedbackService.js';
import { IAgentFeedbackVariableEntry } from '../../common/attachments/chatVariableEntries.js';
import { IAgentFeedbackVariableEntry } from '../../../../workbench/contrib/chat/common/attachments/chatVariableEntries.js';
/**
* Creates the custom hover content for the "N comments" attachment.

View File

@@ -3,24 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from '../../../../../base/common/event.js';
import { Disposable } from '../../../../../base/common/lifecycle.js';
import { URI } from '../../../../../base/common/uri.js';
import { IRange } from '../../../../../editor/common/core/range.js';
import { Comment, CommentThread, CommentThreadCollapsibleState, CommentThreadState, CommentInput } from '../../../../../editor/common/languages.js';
import { createDecorator, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
import { ICommentController, ICommentInfo, ICommentService, INotebookCommentInfo } from '../../../comments/browser/commentService.js';
import { CancellationToken } from '../../../../../base/common/cancellation.js';
import { generateUuid } from '../../../../../base/common/uuid.js';
import { registerAction2, Action2, MenuId } from '../../../../../platform/actions/common/actions.js';
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
import { Codicon } from '../../../../../base/common/codicons.js';
import { localize } from '../../../../../nls.js';
import { isEqual } from '../../../../../base/common/resources.js';
import { IChatEditingService } from '../../common/editing/chatEditingService.js';
import { IAgentSessionsService } from '../agentSessions/agentSessionsService.js';
import { agentSessionContainsResource, editingEntriesContainResource } from '../sessionResourceMatching.js';
import { IChatWidget, IChatWidgetService } from '../chat.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { URI } from '../../../../base/common/uri.js';
import { IRange } from '../../../../editor/common/core/range.js';
import { Comment, CommentThread, CommentThreadCollapsibleState, CommentThreadState, CommentInput } from '../../../../editor/common/languages.js';
import { createDecorator, ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js';
import { ICommentController, ICommentInfo, ICommentService, INotebookCommentInfo } from '../../../../workbench/contrib/comments/browser/commentService.js';
import { CancellationToken } from '../../../../base/common/cancellation.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { registerAction2, Action2, MenuId } from '../../../../platform/actions/common/actions.js';
import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextkey.js';
import { Codicon } from '../../../../base/common/codicons.js';
import { localize } from '../../../../nls.js';
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 --------------------------------------------------------------------

View File

@@ -0,0 +1,32 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.agent-feedback-input-widget {
position: absolute;
z-index: 100;
background-color: var(--vscode-editorWidget-background);
border: 1px solid var(--vscode-editorWidget-border, var(--vscode-contrastBorder));
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
border-radius: 4px;
padding: 4px;
}
.agent-feedback-input-widget input {
background-color: var(--vscode-input-background);
border: 1px solid var(--vscode-input-border, transparent);
color: var(--vscode-input-foreground);
border-radius: 2px;
padding: 2px 6px;
outline: none;
width: 240px;
}
.agent-feedback-input-widget input:focus {
border-color: var(--vscode-focusBorder);
}
.agent-feedback-input-widget input::placeholder {
color: var(--vscode-input-placeholderForeground);
}

View File

@@ -206,7 +206,7 @@ import '../workbench/contrib/speech/browser/speech.contribution.js';
// Chat
import '../workbench/contrib/chat/browser/chat.contribution.js';
import '../workbench/contrib/inlineChat/browser/inlineChat.contribution.js';
//import '../workbench/contrib/inlineChat/browser/inlineChat.contribution.js';
import '../workbench/contrib/mcp/browser/mcp.contribution.js';
import '../workbench/contrib/chat/browser/chatSessions/chatSessions.contribution.js';
import '../workbench/contrib/chat/browser/contextContrib/chatContext.contribution.js';

View File

@@ -165,7 +165,10 @@ import '../workbench/contrib/remoteTunnel/electron-browser/remoteTunnel.contribu
// Chat
import '../workbench/contrib/chat/electron-browser/chat.contribution.js';
import '../workbench/contrib/inlineChat/electron-browser/inlineChat.contribution.js';
//import '../workbench/contrib/inlineChat/electron-browser/inlineChat.contribution.js';
import './contrib/agentFeedback/browser/agentFeedback.contribution.js';
// Encryption
import '../workbench/contrib/encryption/electron-browser/encryption.contribution.js';

View File

@@ -1,29 +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 { EditorResourceAccessor, SideBySideEditor } from '../../../../common/editor.js';
export function getActiveResourceCandidates(input: Parameters<typeof EditorResourceAccessor.getOriginalUri>[0]): URI[] {
const result: URI[] = [];
const resources = EditorResourceAccessor.getOriginalUri(input, { supportSideBySide: SideBySideEditor.BOTH });
if (!resources) {
return result;
}
if (URI.isUri(resources)) {
result.push(resources);
return result;
}
if (resources.secondary) {
result.push(resources.secondary);
}
if (resources.primary) {
result.push(resources.primary);
}
return result;
}

View File

@@ -141,10 +141,6 @@ import { ChatWindowNotifier } from './chatWindowNotifier.js';
import { ChatRepoInfoContribution } from './chatRepoInfo.js';
import { VALID_PROMPT_FOLDER_PATTERN } from '../common/promptSyntax/utils/promptFilesLocator.js';
import { ChatTipService, IChatTipService } from './chatTipService.js';
import { AgentFeedbackService, IAgentFeedbackService } from './agentFeedback/agentFeedbackService.js';
import { AgentFeedbackAttachmentContribution } from './agentFeedback/agentFeedbackAttachment.js';
import { AgentFeedbackEditorOverlay } from './agentFeedback/agentFeedbackEditorOverlay.js';
import { registerAgentFeedbackEditorActions } from './agentFeedback/agentFeedbackEditorActions.js';
import { ChatQueuePickerRendering } from './widget/input/chatQueuePickerActionItem.js';
import { ExploreAgentDefaultModel } from './exploreAgentDefaultModel.js';
import { PlanAgentDefaultModel } from './planAgentDefaultModel.js';
@@ -1482,7 +1478,6 @@ registerWorkbenchContribution2(ChatAgentRecommendation.ID, ChatAgentRecommendati
registerWorkbenchContribution2(ChatEditingEditorAccessibility.ID, ChatEditingEditorAccessibility, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(ChatQueuePickerRendering.ID, ChatQueuePickerRendering, WorkbenchPhase.BlockRestore);
registerWorkbenchContribution2(ChatEditingEditorOverlay.ID, ChatEditingEditorOverlay, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(AgentFeedbackEditorOverlay.ID, AgentFeedbackEditorOverlay, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(SimpleBrowserOverlay.ID, SimpleBrowserOverlay, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(ChatEditingEditorContextKeys.ID, ChatEditingEditorContextKeys, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(ChatTransferContribution.ID, ChatTransferContribution, WorkbenchPhase.BlockRestore);
@@ -1494,7 +1489,6 @@ registerWorkbenchContribution2(UserToolSetsContributions.ID, UserToolSetsContrib
registerWorkbenchContribution2(PromptLanguageFeaturesProvider.ID, PromptLanguageFeaturesProvider, WorkbenchPhase.Eventually);
registerWorkbenchContribution2(ChatWindowNotifier.ID, ChatWindowNotifier, WorkbenchPhase.AfterRestored);
registerWorkbenchContribution2(ChatRepoInfoContribution.ID, ChatRepoInfoContribution, WorkbenchPhase.Eventually);
registerWorkbenchContribution2(AgentFeedbackAttachmentContribution.ID, AgentFeedbackAttachmentContribution, WorkbenchPhase.AfterRestored);
registerChatActions();
registerChatAccessibilityActions();
@@ -1514,7 +1508,6 @@ registerNewChatActions();
registerChatContextActions();
registerChatDeveloperActions();
registerChatEditorActions();
registerAgentFeedbackEditorActions();
registerChatElicitationActions();
registerChatToolActions();
registerLanguageModelActions();
@@ -1551,6 +1544,5 @@ registerSingleton(IChatTodoListService, ChatTodoListService, InstantiationType.D
registerSingleton(IChatOutputRendererService, ChatOutputRendererService, InstantiationType.Delayed);
registerSingleton(IChatLayoutService, ChatLayoutService, InstantiationType.Delayed);
registerSingleton(IChatTipService, ChatTipService, InstantiationType.Delayed);
registerSingleton(IAgentFeedbackService, AgentFeedbackService, InstantiationType.Delayed);
ChatWidget.CONTRIBS.push(ChatDynamicVariableModel);