diff --git a/src/renderer/src/components/activity/activity-thread-actions.test.ts b/src/renderer/src/components/activity/activity-thread-actions.test.ts index 91375ec974b..07f50bce92d 100644 --- a/src/renderer/src/components/activity/activity-thread-actions.test.ts +++ b/src/renderer/src/components/activity/activity-thread-actions.test.ts @@ -98,7 +98,9 @@ describe('activity thread host routing', () => { // Bare setActiveWorktree skips setActiveView('terminal'), initial-terminal seeding and // sleeping-session resume — the workspace dispatcher is the only path that runs them. expect(mocks.activateAndRevealWorkspace).toHaveBeenCalledWith(thread.worktree.id, { - executionHostId: REMOTE_HOST + executionHostId: REMOTE_HOST, + revealInSidebar: false, + clearSidebarFilters: false }) expect(setActiveWorktree).not.toHaveBeenCalled() expect(mocks.activateTabAndFocusPane).toHaveBeenCalledWith( @@ -121,7 +123,9 @@ describe('activity thread host routing', () => { expect(setSelectedPaneKey).toHaveBeenCalledWith(thread.paneKey) expect(mocks.activateAndRevealWorkspace).toHaveBeenCalledWith(thread.worktree.id, { - executionHostId: REMOTE_HOST + executionHostId: REMOTE_HOST, + revealInSidebar: false, + clearSidebarFilters: false }) expect(mocks.activateTabAndFocusPane).toHaveBeenCalledWith( thread.tab.id, @@ -136,7 +140,9 @@ describe('activity thread host routing', () => { makeActions().selectThread(thread) expect(mocks.activateAndRevealWorkspace).toHaveBeenCalledWith(thread.worktree.id, { - executionHostId: REMOTE_HOST + executionHostId: REMOTE_HOST, + revealInSidebar: false, + clearSidebarFilters: false }) expect(mocks.activateTabAndFocusPane).not.toHaveBeenCalled() }) diff --git a/src/renderer/src/components/activity/activity-thread-actions.ts b/src/renderer/src/components/activity/activity-thread-actions.ts index f9f77587a1e..a940129f19c 100644 --- a/src/renderer/src/components/activity/activity-thread-actions.ts +++ b/src/renderer/src/components/activity/activity-thread-actions.ts @@ -83,7 +83,13 @@ export function createActivityThreadActions({ // state of an SSH session that was never revived — has no resident tab until // resumeSleepingAgentSessionsForWorktree/ensureWorktreeHasInitialTerminal run inside here. // Probing tab residency first is what made a remote row click a silent no-op (#16731). - if (activateAndRevealWorkspace(thread.worktree.id, { executionHostId }) === false) { + if ( + activateAndRevealWorkspace(thread.worktree.id, { + executionHostId, + revealInSidebar: false, + clearSidebarFilters: false + }) === false + ) { return } if ( diff --git a/src/renderer/src/lib/worktree-activation-emptied-workspace-reseed.test.ts b/src/renderer/src/lib/worktree-activation-emptied-workspace-reseed.test.ts index 85fa0c0428c..2b85ad88003 100644 --- a/src/renderer/src/lib/worktree-activation-emptied-workspace-reseed.test.ts +++ b/src/renderer/src/lib/worktree-activation-emptied-workspace-reseed.test.ts @@ -1,6 +1,10 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { useAppStore } from '@/store' -import { activateAndRevealFolderWorkspace, activateAndRevealWorktree } from './worktree-activation' +import { + activateAndRevealFolderWorkspace, + activateAndRevealWorkspace, + activateAndRevealWorktree +} from './worktree-activation' import { ensureWorktreeHasInitialTerminal } from './worktree-initial-terminal-seeding' import { folderWorkspaceKey } from '../../../shared/workspace-scope' import { toSshExecutionHostId } from '../../../shared/execution-host' @@ -202,6 +206,25 @@ function seedEmptiedFolderWorkspaceOnTwoHosts(): void { } describe('activating a folder workspace whose last terminal was closed', () => { + it.each(['local', SSH_HOST_ID] as const)( + 'opens a notification on %s without revealing the folder', + (executionHostId) => { + seedEmptiedFolderWorkspaceOnTwoHosts() + useAppStore.setState({ sidebarBody: 'agents' }) + + const result = activateAndRevealWorkspace(FOLDER_KEY, { + executionHostId, + revealInSidebar: false, + clearSidebarFilters: false + }) + + expect(result).not.toBe(false) + expect(useAppStore.getState().activeWorktreeId).toBe(FOLDER_KEY) + expect(useAppStore.getState().sidebarBody).toBe('agents') + expect(useAppStore.getState().revealWorktreeInSidebar).not.toHaveBeenCalled() + } + ) + it('re-seeds a terminal when the workspace is opened', () => { seedEmptiedFolderWorkspaceOnTwoHosts() diff --git a/src/renderer/src/lib/worktree-activation.ts b/src/renderer/src/lib/worktree-activation.ts index fbb464fda49..22bc909e6b7 100644 --- a/src/renderer/src/lib/worktree-activation.ts +++ b/src/renderer/src/lib/worktree-activation.ts @@ -79,6 +79,7 @@ export function activateAndRevealFolderWorkspace( folderWorkspaceId: string, opts?: { sidebarRevealBehavior?: PendingSidebarWorktreeReveal['behavior'] + revealInSidebar?: boolean startup?: WorktreeStartupPayload runtimeEnvironmentId?: string | null executionHostId?: ExecutionHostId @@ -163,10 +164,11 @@ export function activateAndRevealFolderWorkspace( opts?.providesInitialSurface ) - if (opts?.sidebarRevealBehavior) { - state.revealWorktreeInSidebar(workspaceKey, { behavior: opts.sidebarRevealBehavior }) - } else { - state.revealWorktreeInSidebar(workspaceKey) + if (opts?.revealInSidebar !== false) { + state.revealWorktreeInSidebar( + workspaceKey, + opts?.sidebarRevealBehavior ? { behavior: opts.sidebarRevealBehavior } : undefined + ) } return { primaryTabId } @@ -346,8 +348,8 @@ export function activateAndRevealWorkspace( opts?: { executionHostId?: ExecutionHostId providesInitialSurface?: boolean - /** Worktree-only: folder workspaces are never filter-hidden, so these are dropped there. */ revealInSidebar?: boolean + /** Worktree-only: folder workspaces are never filter-hidden. */ clearSidebarFilters?: boolean } ): ActivateAndRevealResult | false { @@ -355,8 +357,7 @@ export function activateAndRevealWorkspace( if (workspaceScope?.type !== 'folder') { return activateAndRevealWorktree(workspaceId, opts) } - const { revealInSidebar: _reveal, clearSidebarFilters: _clear, ...folderOpts } = opts ?? {} - return activateAndRevealFolderWorkspace(workspaceScope.folderWorkspaceId, folderOpts) + return activateAndRevealFolderWorkspace(workspaceScope.folderWorkspaceId, opts) } // Why: break the import cycle — nav-history slice (under @/store) can't import activation directly, so register the activator here.