From 670e6a6fdd0bc3f3a57d248da7c493b9cfe526d7 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 8 May 2026 18:31:35 +0700 Subject: [PATCH] sidebar history: drop workspace filter, project-only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes the Workspace section from the Sessions filter dropdown. Final dropdown is All + Project. Simplifies the filter discriminated union (drops the "workspace" variant), the predicate, and the hook-derived option list. Workspace mapping is still used internally to map session cwd to project for the Project filter and for hiding unmapped agents. E2E journey simplified — the workspace-filter step is gone, including its brittle accessible-name regex. --- .../app/e2e/sidebar-history-sessions.spec.ts | 13 +----- .../src/sidebar-sessions/controller.test.ts | 8 ++-- .../session-filtering.test.ts | 21 ++-------- .../src/sidebar-sessions/session-filtering.ts | 22 +--------- packages/app/src/sidebar-sessions/toggle.tsx | 40 ------------------- packages/app/src/sidebar-sessions/types.ts | 5 +-- .../use-sidebar-session-workspaces.test.tsx | 6 +-- .../use-sidebar-session-workspaces.ts | 7 +--- 8 files changed, 16 insertions(+), 106 deletions(-) diff --git a/packages/app/e2e/sidebar-history-sessions.spec.ts b/packages/app/e2e/sidebar-history-sessions.spec.ts index 9e4d3e8553..c2367513d8 100644 --- a/packages/app/e2e/sidebar-history-sessions.spec.ts +++ b/packages/app/e2e/sidebar-history-sessions.spec.ts @@ -256,10 +256,6 @@ async function chooseSessionsFilter(page: Page, name: string | RegExp) { await page.getByRole("button", { name }).click(); } -async function chooseWorkspaceSessionsFilter(page: Page, workspaceId: string) { - await chooseSessionsFilter(page, new RegExp(`^${escapeRegex(workspaceId)}\\s`)); -} - async function chooseProjectSessionsFilter(page: Page, projectName: string) { await chooseSessionsFilter(page, new RegExp(`^${escapeRegex(projectName)}$`)); } @@ -319,11 +315,6 @@ async function runSidebarHistorySessionsJourney(page: Page) { await switchSidebarToWorkspaces(page, seeded); await switchSidebarToSessions(page); - await chooseWorkspaceSessionsFilter(page, seeded.firstWorkspace.workspaceId); - await expectOnlySidebarSessionRows(page, { - visible: [middle, oldest], - hidden: [newest], - }); await chooseProjectSessionsFilter(page, seeded.secondProjectName); await expectOnlySidebarSessionRows(page, { visible: [newest], @@ -351,9 +342,7 @@ async function runSidebarHistorySessionsJourney(page: Page) { test.describe("Sidebar History Sessions journey", () => { test.describe.configure({ timeout: 300_000 }); - test("toggles sessions, filters by workspace and project, and opens a session tab", async ({ - page, - }) => { + test("toggles sessions, filters by project, and opens a session tab", async ({ page }) => { await runSidebarHistorySessionsJourney(page); }); }); diff --git a/packages/app/src/sidebar-sessions/controller.test.ts b/packages/app/src/sidebar-sessions/controller.test.ts index 7693ebf435..3bc82ea8fd 100644 --- a/packages/app/src/sidebar-sessions/controller.test.ts +++ b/packages/app/src/sidebar-sessions/controller.test.ts @@ -14,14 +14,14 @@ describe("useSidebarSessionsController", () => { act(() => { result.current.setSidebarSessionFilter({ - type: "workspace", - workspaceKey: "server-1:workspace-1", + type: "project", + projectKey: "project-a", }); }); expect(result.current.sidebarSessionFilter).toEqual({ - type: "workspace", - workspaceKey: "server-1:workspace-1", + type: "project", + projectKey: "project-a", }); rerender({ serverId: "server-2" }); diff --git a/packages/app/src/sidebar-sessions/session-filtering.test.ts b/packages/app/src/sidebar-sessions/session-filtering.test.ts index 495f4a13c7..d2cf324647 100644 --- a/packages/app/src/sidebar-sessions/session-filtering.test.ts +++ b/packages/app/src/sidebar-sessions/session-filtering.test.ts @@ -76,20 +76,6 @@ describe("sidebar session filtering", () => { expect(visibleIds).toEqual(["main", "docs", "api"]); }); - it("filters by workspace", () => { - const lookup = createSidebarSessionWorkspaceLookup(WORKSPACES); - - const visibleIds = AGENTS.filter((agent) => - shouldIncludeSidebarSessionAgent({ - agent, - filter: { type: "workspace", workspaceKey: "server-1:workspace-2" }, - lookup, - }), - ).map((agent) => agent.id); - - expect(visibleIds).toEqual(["docs"]); - }); - it("filters by project", () => { const lookup = createSidebarSessionWorkspaceLookup(WORKSPACES); @@ -121,7 +107,6 @@ describe("sidebar session filtering", () => { }); expect(availability).toEqual({ - workspaceKeys: ["server-1:workspace-1"], projectKeys: ["project-a"], }); const filterProjects = deriveSidebarSessionFilterProjects({ @@ -192,11 +177,13 @@ describe("sidebar session filtering", () => { }, ], availability, - workspaceNameByKey: new Map([["server-1:workspace-1", "Main"]]), }); expect(filterProjects.map(projectWorkspaceKeys)).toEqual([ - { projectKey: "project-a", workspaceKeys: ["server-1:workspace-1"] }, + { + projectKey: "project-a", + workspaceKeys: ["server-1:workspace-1", "server-1:workspace-3"], + }, ]); }); }); diff --git a/packages/app/src/sidebar-sessions/session-filtering.ts b/packages/app/src/sidebar-sessions/session-filtering.ts index 62d7e9ea05..bb626f7fa9 100644 --- a/packages/app/src/sidebar-sessions/session-filtering.ts +++ b/packages/app/src/sidebar-sessions/session-filtering.ts @@ -8,7 +8,6 @@ export interface SidebarSessionWorkspaceLookup { } export interface SidebarSessionFilterAvailability { - workspaceKeys: readonly string[]; projectKeys: readonly string[]; } @@ -75,9 +74,6 @@ export function shouldIncludeSidebarSessionAgent(input: { if (input.filter.type === "all") { return true; } - if (input.filter.type === "workspace") { - return workspace.workspaceKey === input.filter.workspaceKey; - } return workspace.projectKey === input.filter.projectKey; } @@ -85,7 +81,6 @@ export function deriveSidebarSessionFilterAvailability(input: { agents: readonly SidebarSessionAgent[]; lookup: SidebarSessionWorkspaceLookup; }): SidebarSessionFilterAvailability { - const workspaceKeys = new Set(); const projectKeys = new Set(); for (const agent of input.agents) { @@ -96,12 +91,10 @@ export function deriveSidebarSessionFilterAvailability(input: { if (!workspace) { continue; } - workspaceKeys.add(workspace.workspaceKey); projectKeys.add(workspace.projectKey); } return { - workspaceKeys: Array.from(workspaceKeys).sort(), projectKeys: Array.from(projectKeys).sort(), }; } @@ -109,13 +102,11 @@ export function deriveSidebarSessionFilterAvailability(input: { export function deriveSidebarSessionFilterProjects(input: { projects: readonly SidebarProjectEntry[]; availability: SidebarSessionFilterAvailability; - workspaceNameByKey: ReadonlyMap; }): SidebarProjectEntry[] { - if (input.projects.length === 0 || input.availability.workspaceKeys.length === 0) { + if (input.projects.length === 0 || input.availability.projectKeys.length === 0) { return []; } - const visibleWorkspaceKeys = new Set(input.availability.workspaceKeys); const visibleProjectKeys = new Set(input.availability.projectKeys); const projects: SidebarProjectEntry[] = []; @@ -123,16 +114,7 @@ export function deriveSidebarSessionFilterProjects(input: { if (!visibleProjectKeys.has(project.projectKey)) { continue; } - const workspaces = project.workspaces - .filter((workspace) => visibleWorkspaceKeys.has(workspace.workspaceKey)) - .map((workspace) => { - const name = input.workspaceNameByKey.get(workspace.workspaceKey); - return name && name !== workspace.name ? Object.assign({}, workspace, { name }) : workspace; - }); - if (workspaces.length === 0) { - continue; - } - projects.push({ ...project, workspaces }); + projects.push(project); } return projects; diff --git a/packages/app/src/sidebar-sessions/toggle.tsx b/packages/app/src/sidebar-sessions/toggle.tsx index 5dd3453647..5b834a4ab3 100644 --- a/packages/app/src/sidebar-sessions/toggle.tsx +++ b/packages/app/src/sidebar-sessions/toggle.tsx @@ -128,22 +128,6 @@ function SidebarSessionsFilterMenu({ {visibleFilterProjects.length > 0 ? ( <> - - Workspace - {visibleFilterProjects.flatMap((project) => - project.workspaces.map((workspace) => ( - - )), - )} Project {visibleFilterProjects.map((project) => ( @@ -225,30 +209,6 @@ function FilterSectionHeading({ children }: { children: string }) { ); } -function WorkspaceFilterItem({ - selected, - label, - description, - workspaceKey, - onFilterChange, -}: { - selected: boolean; - label: string; - description: string; - workspaceKey: string; - onFilterChange: (filter: SidebarSessionFilter) => void; -}) { - const handleSelect = useCallback(() => { - onFilterChange({ type: "workspace", workspaceKey }); - }, [onFilterChange, workspaceKey]); - - return ( - - {label} - - ); -} - function ProjectFilterItem({ selected, label, diff --git a/packages/app/src/sidebar-sessions/types.ts b/packages/app/src/sidebar-sessions/types.ts index 5ce26b9076..bfc8b9ef80 100644 --- a/packages/app/src/sidebar-sessions/types.ts +++ b/packages/app/src/sidebar-sessions/types.ts @@ -2,10 +2,7 @@ import type { AggregatedAgent } from "@/hooks/use-aggregated-agents"; export type SidebarSessionViewMode = "workspaces" | "sessions"; -export type SidebarSessionFilter = - | { type: "all" } - | { type: "workspace"; workspaceKey: string } - | { type: "project"; projectKey: string }; +export type SidebarSessionFilter = { type: "all" } | { type: "project"; projectKey: string }; export interface SidebarSessionWorkspace { serverId: string; diff --git a/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.test.tsx b/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.test.tsx index be81763726..066a3fd0ee 100644 --- a/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.test.tsx +++ b/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.test.tsx @@ -97,7 +97,7 @@ afterEach(() => { }); describe("useVisibleSidebarSessionFilterProjects", () => { - it("uses the hydrated workspace branch label for workspace filter options", () => { + it("returns projects with mapped active sessions", () => { act(() => { useSessionStore.getState().initializeSession("server-1", {} as unknown as DaemonClient); useSessionStore.getState().setWorkspaces("server-1", new Map([["workspace-1", WORKSPACE]])); @@ -111,8 +111,6 @@ describe("useVisibleSidebarSessionFilterProjects", () => { }), ); - expect(result.current[0]?.workspaces[0]?.name).toBe("feat-foo"); - expect(result.current[0]?.workspaces[0]?.name).not.toBe("/abs/path/to/repo"); - expect(result.current[0]?.workspaces[0]?.name).not.toBe("repo"); + expect(result.current.map((project) => project.projectKey)).toEqual(["project-a"]); }); }); diff --git a/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.ts b/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.ts index 5897c45bca..d792e60514 100644 --- a/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.ts +++ b/packages/app/src/sidebar-sessions/use-sidebar-session-workspaces.ts @@ -14,7 +14,7 @@ import { } from "./session-filtering"; const EMPTY_WORKSPACES: SidebarSessionWorkspace[] = []; -const EMPTY_AVAILABILITY = { workspaceKeys: [], projectKeys: [] } as const; +const EMPTY_AVAILABILITY = { projectKeys: [] } as const; export function useSidebarSessionWorkspaces(input: { serverId: string | null; @@ -108,10 +108,7 @@ export function useVisibleSidebarSessionFilterProjects(input: { deriveSidebarSessionFilterProjects({ projects: input.projects, availability, - workspaceNameByKey: new Map( - workspaces.map((workspace) => [workspace.workspaceKey, workspace.workspaceName]), - ), }), - [availability, input.projects, workspaces], + [availability, input.projects], ); }