Merge pull request #303299 from microsoft/copilot/inherent-hornet

Collapse inactive repo sections in agent sessions view
This commit is contained in:
Osvaldo Ortega
2026-03-19 14:42:57 -06:00
committed by GitHub
4 changed files with 32 additions and 2 deletions

View File

@@ -242,6 +242,8 @@ export class AgenticSessionsViewPane extends ViewPane {
this.storageService.store(GROUPING_STORAGE_KEY, this.currentGrouping, StorageScope.PROFILE, StorageTarget.USER);
this.isGroupedByRepoKey?.set(this.currentGrouping === AgentSessionsGrouping.Repository);
// TODO @osortega: Unsure if this is going to be annoying or helpful so that you can quickly see the active sessions
this.sessionsControl?.resetSectionCollapseState();
this.sessionsControl?.update();
}
}

View File

@@ -172,6 +172,7 @@ export interface IAgentSessionsControl {
clearFocus(): void;
hasFocusOrSelection(): boolean;
resetSectionCollapseState(): void;
collapseAllSections(): void;
}

View File

@@ -13,7 +13,7 @@ import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent
import { KeyCode } from '../../../../../base/common/keyCodes.js';
import { localize } from '../../../../../nls.js';
import { AgentSessionSection, IAgentSession, IAgentSessionSection, IAgentSessionsModel, IMarshalledAgentSessionContext, isAgentSession, isAgentSessionSection } from './agentSessionsModel.js';
import { AgentSessionListItem, AgentSessionRenderer, AgentSessionsAccessibilityProvider, AgentSessionsCompressionDelegate, AgentSessionsDataSource, AgentSessionsDragAndDrop, AgentSessionsIdentityProvider, AgentSessionsKeyboardNavigationLabelProvider, AgentSessionsListDelegate, AgentSessionSectionRenderer, AgentSessionsSorter, IAgentSessionsFilter } from './agentSessionsViewer.js';
import { AgentSessionListItem, AgentSessionRenderer, AgentSessionsAccessibilityProvider, AgentSessionsCompressionDelegate, AgentSessionsDataSource, AgentSessionsDragAndDrop, AgentSessionsIdentityProvider, AgentSessionsKeyboardNavigationLabelProvider, AgentSessionsListDelegate, AgentSessionSectionRenderer, AgentSessionSectionLabels, AgentSessionsSorter, getRepositoryName, IAgentSessionsFilter } from './agentSessionsViewer.js';
import { AgentSessionsGrouping } from './agentSessionsFilter.js';
import { AgentSessionApprovalModel } from './agentSessionApprovalModel.js';
import { FuzzyScore } from '../../../../../base/common/filters.js';
@@ -79,8 +79,11 @@ export class AgentSessionsControl extends Disposable implements IAgentSessionsCo
private emptyFilterMessage: HTMLElement | undefined;
private sessionsList: WorkbenchCompressibleAsyncDataTree<IAgentSessionsModel, AgentSessionListItem, FuzzyScore> | undefined;
private static readonly RECENT_SESSIONS_FOR_EXPAND = 5;
private sessionsListFindIsOpen = false;
private _isProgrammaticCollapseChange = false;
private readonly _recentRepositoryLabels = new Set<string>();
private readonly updateSessionsListThrottler = this._register(new Throttler());
@@ -213,6 +216,10 @@ export class AgentSessionsControl extends Disposable implements IAgentSessionsCo
this.storageService.store(AgentSessionsControl.SECTION_COLLAPSE_STATE_KEY, JSON.stringify(state), StorageScope.PROFILE, StorageTarget.USER);
}
resetSectionCollapseState(): void {
this.storageService.remove(AgentSessionsControl.SECTION_COLLAPSE_STATE_KEY, StorageScope.PROFILE);
}
private createList(container: HTMLElement): void {
const collapseByDefault = (element: unknown) => {
if (isAgentSessionSection(element)) {
@@ -236,6 +243,9 @@ export class AgentSessionsControl extends Disposable implements IAgentSessionsCo
if (element.section === AgentSessionSection.Yesterday && this.hasTodaySessions()) {
return true; // Also collapse Yesterday when there are sessions from Today
}
if (element.section === AgentSessionSection.Repository && !this._recentRepositoryLabels.has(element.label)) {
return true; // Collapse repository sections that don't contain recent sessions
}
}
}
@@ -303,6 +313,7 @@ export class AgentSessionsControl extends Disposable implements IAgentSessionsCo
}
}));
this.computeRecentRepositoryLabels();
list.setInput(model);
this._register(list.onDidOpen(e => this.openAgentSession(e)));
@@ -374,6 +385,20 @@ export class AgentSessionsControl extends Disposable implements IAgentSessionsCo
);
}
private computeRecentRepositoryLabels(): void {
this._recentRepositoryLabels.clear();
const sessions = this.agentSessionsService.model.sessions
.filter(s => !s.isArchived() && !s.isPinned())
.sort((a, b) => b.timing.created - a.timing.created)
.slice(0, AgentSessionsControl.RECENT_SESSIONS_FOR_EXPAND);
for (const session of sessions) {
const name = getRepositoryName(session);
this._recentRepositoryLabels.add(name ?? AgentSessionSectionLabels[AgentSessionSection.Repository]);
}
}
private async openAgentSession(e: IOpenEvent<AgentSessionListItem | undefined>): Promise<void> {
const element = e.element;
if (!element || isAgentSessionSection(element)) {
@@ -522,6 +547,7 @@ export class AgentSessionsControl extends Disposable implements IAgentSessionsCo
async update(): Promise<void> {
return this.updateSessionsListThrottler.queue(async () => {
this.computeRecentRepositoryLabels();
await this.sessionsList?.updateChildren();
this._onDidUpdate.fire();

View File

@@ -942,7 +942,7 @@ export class AgentSessionsDataSource extends Disposable implements IAsyncDataSou
if (otherSessions.length > 0) {
result.push({
section: AgentSessionSection.Repository,
label: localize('agentSessions.noRepository', "Other"),
label: AgentSessionSectionLabels[AgentSessionSection.Repository],
sessions: otherSessions,
});
}
@@ -1110,6 +1110,7 @@ export const AgentSessionSectionLabels = {
[AgentSessionSection.Older]: localize('agentSessions.olderSection', "Older"),
[AgentSessionSection.Archived]: localize('agentSessions.archivedSection', "Archived"),
[AgentSessionSection.More]: localize('agentSessions.moreSection', "More"),
[AgentSessionSection.Repository]: localize('agentSessions.noRepository', "Other"),
};
const DAY_THRESHOLD = 24 * 60 * 60 * 1000;