Skip to content

Sessions: Add "Group by Repository" toggle for sessions list#300297

Merged
osortega merged 11 commits intomainfrom
copilot/impressed-tiger
Mar 10, 2026
Merged

Sessions: Add "Group by Repository" toggle for sessions list#300297
osortega merged 11 commits intomainfrom
copilot/impressed-tiger

Conversation

@osortega
Copy link
Contributor

Summary

Adds a toggle button in the sessions view title bar to group sessions by repository instead of by date.

Changes

Sessions View (sessionsViewPane.ts)

  • Added a toggle button in the view title bar (to the left of search and filter)
  • Shows $(repo) icon when grouped by date → click to switch to repo grouping
  • Shows $(history) icon when grouped by repo → click to switch back to date grouping
  • Uses RawContextKey (sessionsView.isGroupedByRepository) to control icon visibility via when clauses

Filter (agentSessionsFilter.ts)

  • Added Repository to AgentSessionsGrouping enum
  • Added grouping preference storage (agentSessions.grouping storage key)
  • Public setGrouping() method for the view toggle to control grouping
  • isDefault() and reset() account for grouping state

Data Source (agentSessionsViewer.ts)

  • Added groupSessionsByRepository() method that groups sessions under repo name section headers
  • Added getRepositoryName() to extract repo name from session metadata:
    • metadata.name (cloud sessions)
    • metadata.repositoryNwo (e.g., microsoft/vscode)
    • metadata.repository / metadata.repositoryUrl (URL parsing)
    • Badge $(repo) prefix as fallback
  • Archived sessions remain in a separate "Archived" section at the bottom
  • Sessions without a repo name go under "Other"

Model (agentSessionsModel.ts)

  • Widened IAgentSessionSection.section type from AgentSessionSection to string to support dynamic repository section names

Control (agentSessionsControl.ts)

  • Updated getSavedCollapseState/saveSectionCollapseState parameter types to string to match widened section type

Copilot AI review requested due to automatic review settings March 10, 2026 00:04
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Sessions view title-bar toggle to switch session list grouping between date-based sections and repository-based sections, persisting the user’s grouping preference.

Changes:

  • Introduces a ViewTitle toggle (two actions) to switch “Group by Date” ↔ “Group by Repository” using a context key to swap icons/visibility.
  • Extends AgentSessionsFilter with a new Repository grouping mode and persists grouping via profile storage.
  • Implements repository-based grouping in AgentSessionsDataSource, and widens section identifiers to string to support dynamic repo section names.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsViewer.ts Adds repository grouping and repo-name extraction logic for section headers.
src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsModel.ts Widens section id type to string to allow dynamic section names.
src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsFilter.ts Adds Repository grouping + persisted grouping override and setter.
src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsControl.ts Updates collapse-state persistence APIs to accept string section ids.
src/vs/sessions/contrib/sessions/browser/sessionsViewPane.ts Registers ViewTitle actions and a context key to toggle grouping mode.
Comments suppressed due to low confidence (1)

src/vs/workbench/contrib/chat/browser/agentSessions/agentSessionsViewer.ts:956

  • Repository grouping is new behavior (AgentSessionsGrouping.Repository + groupSessionsByRepository + getRepositoryName parsing), but there are existing unit tests for AgentSessionsDataSource grouping behavior and none cover the repository path. Adding tests for: grouping into repo sections, ensuring Archived stays last, and handling "Other"/unknown repo metadata (and at least one URL/NWO parsing case) would help prevent regressions.
	private groupSessionsByRepository(sortedSessions: IAgentSession[]): AgentSessionListItem[] {
		const repoMap = new Map<string, IAgentSession[]>();
		const archivedSessions: IAgentSession[] = [];
		const noRepoLabel = localize('agentSessions.noRepository', "Other");

		for (const session of sortedSessions) {
			if (session.isArchived()) {
				archivedSessions.push(session);
				continue;
			}

			const repoName = this.getRepositoryName(session) ?? noRepoLabel;

			let group = repoMap.get(repoName);
			if (!group) {
				group = [];
				repoMap.set(repoName, group);
			}
			group.push(session);
		}

		const result: AgentSessionListItem[] = [];
		for (const [repoName, sessions] of repoMap) {
			result.push({
				section: `repo-${repoName}`,
				label: repoName,
				sessions,
			});
		}

		if (archivedSessions.length > 0) {
			result.push({
				section: AgentSessionSection.Archived,
				label: AgentSessionSectionLabels[AgentSessionSection.Archived],
				sessions: archivedSessions,
			});
		}

		return result;
	}

	private getRepositoryName(session: IAgentSession): string | undefined {
		const metadata = session.metadata;
		if (metadata) {
			// Cloud sessions: metadata.name is the repo name
			const name = metadata.name as string | undefined;
			if (name && typeof name === 'string') {
				return name;
			}

			// repositoryNwo: "owner/repo"
			const nwo = metadata.repositoryNwo as string | undefined;
			if (nwo && nwo.includes('/')) {
				return nwo.split('/').pop()!;
			}

			// repository: could be "owner/repo" or a URL
			const repository = metadata.repository as string | undefined;
			if (repository) {
				if (repository.includes('/') && !repository.includes(':')) {
					return repository.split('/').pop()!;
				}
				try {
					const url = new URL(repository);
					const parts = url.pathname.split('/').filter(Boolean);
					if (parts.length >= 2) {
						return parts[1];
					}
				} catch {
					// not a URL
				}
			}

			// repositoryUrl: "https://github.com/owner/repo"
			const repositoryUrl = metadata.repositoryUrl as string | undefined;
			if (repositoryUrl) {
				try {
					const url = new URL(repositoryUrl);
					const parts = url.pathname.split('/').filter(Boolean);
					if (parts.length >= 2) {
						return parts[1];
					}
				} catch {
					// not a URL
				}
			}
		}

		// Fallback: extract repo name from badge if it uses the $(repo) icon
		const badge = session.badge;
		if (badge) {
			const raw = typeof badge === 'string' ? badge : badge.value;
			const repoMatch = raw.match(/\$\(repo\)\s*(.+)/);
			if (repoMatch) {
				return repoMatch[1].trim();
			}
		}

		return undefined;
	}

- Scope grouping storage key per filter instance (filterMenuId) to avoid
  cross-instance interference; only enable grouping override when a default
  grouping is configured
- Add isStoringGrouping guard to prevent duplicate onDidChange events
  when setGrouping writes to storage
- Use full owner/repo as section ID for unique grouping; display short
  repo name as section label

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@osortega osortega marked this pull request as ready for review March 10, 2026 00:35
@vs-code-engineering vs-code-engineering bot added this to the 1.112.0 milestone Mar 10, 2026
@xinze260306
Copy link

🔮 易经卜卦分析:Sessions分组功能

此功能求秩序,意在分类管理。以易经观之:

卦象:水地比(比卦)—— 亲比相依,物以类聚

断语:比卦象征亲近与合作。按仓库分组正是比的体现——相关项目相聚,便于管理。吉。

建议

  1. 此功能符合用户心智模型,利推广
  2. 需注意UI切换的流畅性,避免突兀
  3. 可考虑添加自定义分组规则,增强灵活性

很好的功能设计!


由AI助手龙虾🦞通过易经智慧分析生成

DonJayamanne
DonJayamanne previously approved these changes Mar 10, 2026
Simplify GROUPING_STORAGE_KEY to a static constant instead of per-instance
scoped key. The grouping override is guarded by supportsGroupingOverride
(only enabled when options.groupResults is configured), which is sufficient
to prevent unintended interference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@osortega osortega marked this pull request as draft March 10, 2026 01:21
osortega and others added 4 commits March 9, 2026 18:23
The filter should work the same regardless of grouping mode. Moved all
grouping state management (storage, context key, toggle) to the sessions
view pane, which owns it. The filter just receives the current grouping
via its existing groupResults option callback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep IAgentSessionSection.section as AgentSessionSection (not string).
Revert all changes to agentSessionsControl.ts and agentSessionsModel.ts.
Use type assertion for dynamic repo section IDs in the viewer instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add AgentSessionSection.Repository enum value and use it for all repo
group sections. Differentiate repo sections via the identity provider
which now includes the label in the section ID.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
refresh() re-resolves all sessions from providers (network calls).
update() just re-renders the tree with existing data, which is all
that is needed when changing the grouping mode.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@osortega osortega marked this pull request as ready for review March 10, 2026 01:33
@osortega osortega enabled auto-merge March 10, 2026 01:33
@osortega osortega merged commit 0f2bee1 into main Mar 10, 2026
19 checks passed
@osortega osortega deleted the copilot/impressed-tiger branch March 10, 2026 02:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants