diff --git a/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackService.ts b/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackService.ts index 773968080fa..7028d35b068 100644 --- a/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackService.ts +++ b/src/vs/sessions/contrib/agentFeedback/browser/agentFeedbackService.ts @@ -27,6 +27,7 @@ import { isAgentHostProviderId } from '../../../common/agentHostSessionsProvider import { AnnotationsAgentFeedbackItemsBackend, IAgentFeedbackItemsBackend, InMemoryAgentFeedbackItemsBackend } from './agentFeedbackItemsBackend.js'; import { ATTACHMENT_ID_PREFIX, createAgentFeedbackVariableEntry } from './agentFeedbackAttachmentEntry.js'; import { AgentFeedbackKind, AgentFeedbackState, type IAgentFeedback } from './agentFeedbackModel.js'; +import { SessionEditorCommentSource, toSessionEditorCommentId } from './sessionEditorComments.js'; // --- Types -------------------------------------------------------------------- @@ -549,7 +550,8 @@ export class AgentFeedbackService extends Disposable implements IAgentFeedbackSe if (!feedback) { return; } - await this.revealSessionComment(sessionResource, feedbackId, feedback.resourceUri, feedback.range); + // Anchor using the session-editor-comment id (not the raw feedback id) so the editor widget contribution matches the active item and expands its widget. + await this.revealSessionComment(sessionResource, toSessionEditorCommentId(SessionEditorCommentSource.AgentFeedback, feedbackId), feedback.resourceUri, feedback.range); } async revealSessionComment(sessionResource: URI, commentId: string, resourceUri: URI, range: IRange): Promise { diff --git a/src/vs/sessions/contrib/agentFeedback/browser/sessionEditorComments.ts b/src/vs/sessions/contrib/agentFeedback/browser/sessionEditorComments.ts index 5624f43a545..e4bce498f03 100644 --- a/src/vs/sessions/contrib/agentFeedback/browser/sessionEditorComments.ts +++ b/src/vs/sessions/contrib/agentFeedback/browser/sessionEditorComments.ts @@ -5,7 +5,7 @@ import { IRange, Range } from '../../../../editor/common/core/range.js'; import { URI } from '../../../../base/common/uri.js'; -import { AgentFeedbackKind, AgentFeedbackState, IAgentFeedback } from './agentFeedbackService.js'; +import { AgentFeedbackKind, AgentFeedbackState, IAgentFeedback } from './agentFeedbackModel.js'; import { ICodeReviewSuggestion, IPRReviewComment, IPRReviewState, PRReviewStateKind } from '../../codeReview/browser/codeReviewService.js'; export const enum SessionEditorCommentSource { diff --git a/src/vs/sessions/contrib/agentFeedback/test/browser/agentFeedbackService.test.ts b/src/vs/sessions/contrib/agentFeedback/test/browser/agentFeedbackService.test.ts index 1b5353990de..dc806720b68 100644 --- a/src/vs/sessions/contrib/agentFeedback/test/browser/agentFeedbackService.test.ts +++ b/src/vs/sessions/contrib/agentFeedback/test/browser/agentFeedbackService.test.ts @@ -12,6 +12,7 @@ import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/tes import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js'; import { mock } from '../../../../../base/test/common/mock.js'; import { AgentFeedbackKind, AgentFeedbackService, AgentFeedbackState, IAgentFeedbackService } from '../../browser/agentFeedbackService.js'; +import { getSessionEditorComments } from '../../browser/sessionEditorComments.js'; import { IChatEditingService } from '../../../../../workbench/contrib/chat/common/editing/chatEditingService.js'; import { IChatWidget, IChatWidgetService } from '../../../../../workbench/contrib/chat/browser/chat.js'; import { IAgentFeedbackVariableEntry } from '../../../../../workbench/contrib/chat/common/attachments/chatVariableEntries.js'; @@ -51,6 +52,7 @@ suite('AgentFeedbackService - Ordering', () => { instantiationService.stub(IEditorService, new class extends mock() { override onDidVisibleEditorsChange = Event.None; override visibleEditorPanes = []; + override openEditor(..._args: unknown[]): Promise { return Promise.resolve(undefined); } }); instantiationService.stub(ISessionsManagementService, new class extends mock() { override getSession(_resource: URI) { return undefined; } @@ -191,6 +193,25 @@ suite('AgentFeedbackService - Ordering', () => { assert.strictEqual(bearing.activeIdx, 2); }); + test('revealFeedback anchors the matching session editor comment so its widget expands', async () => { + const f1 = service.addFeedback(session, fileA, r(5), 'A:5'); + const f2 = service.addFeedback(session, fileA, r(20), 'A:20'); + + // The editor widget contribution expands the widget whose session + // editor comment matches the navigation anchor. revealFeedback must set + // the anchor using the prefixed session-editor-comment id (not the raw + // feedback id) for that match to succeed. + await service.revealFeedback(session, f2.id); + + const comments = getSessionEditorComments(session, service.getFeedback(session)); + const bearing = service.getNavigationBearing(session, comments); + assert.strictEqual(comments[bearing.activeIdx]?.sourceId, f2.id); + + await service.revealFeedback(session, f1.id); + const bearingAfter = service.getNavigationBearing(session, comments); + assert.strictEqual(comments[bearingAfter.activeIdx]?.sourceId, f1.id); + }); + test('removing feedback preserves ordering', () => { const f1 = service.addFeedback(session, fileA, r(30), 'A:30'); service.addFeedback(session, fileA, r(10), 'A:10');