From d2de9580e181b3cabb3b84c6e970bd3902eb13d3 Mon Sep 17 00:00:00 2001 From: Sahibzada Allahyar Date: Thu, 4 Jun 2026 18:08:47 +0100 Subject: [PATCH] fix(desktop): prefer configured workspace cwd --- .../session/hooks/use-hermes-config.test.ts | 106 ++++++++++++++++++ .../app/session/hooks/use-hermes-config.ts | 5 +- 2 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 apps/desktop/src/app/session/hooks/use-hermes-config.test.ts diff --git a/apps/desktop/src/app/session/hooks/use-hermes-config.test.ts b/apps/desktop/src/app/session/hooks/use-hermes-config.test.ts new file mode 100644 index 000000000..7f3737a93 --- /dev/null +++ b/apps/desktop/src/app/session/hooks/use-hermes-config.test.ts @@ -0,0 +1,106 @@ +import { act, renderHook } from '@testing-library/react' +// @vitest-environment jsdom +import { beforeEach, describe, expect, it, vi } from 'vitest' + +import { getHermesConfig } from '@/hermes' +import { persistString } from '@/lib/storage' +import { $currentCwd, setCurrentCwd } from '@/store/session' + +import { useHermesConfig } from './use-hermes-config' + +vi.mock('@/hermes', () => ({ + getHermesConfig: vi.fn(), + getHermesConfigDefaults: vi.fn().mockResolvedValue({}), +})) + +const WORKSPACE_CWD_KEY = 'hermes.desktop.workspace-cwd' + +describe('useHermesConfig refreshHermesConfig', () => { + beforeEach(() => { + // Reset atoms and localStorage between tests + setCurrentCwd('') + persistString(WORKSPACE_CWD_KEY, null) + }) + + it('applies terminal.cwd from config even when localStorage has a stale value', async () => { + // Simulate a stale remembered workspace cwd + persistString(WORKSPACE_CWD_KEY, '/Users/old/stale-project') + setCurrentCwd('/Users/old/stale-project') + + vi.mocked(getHermesConfig).mockResolvedValue({ + terminal: { cwd: '/Users/example/new-workspace' }, + } as any) + + const { result } = renderHook(() => + useHermesConfig({ + activeSessionIdRef: { current: null }, + refreshProjectBranch: vi.fn().mockResolvedValue(undefined), + }), + ) + + await act(async () => { + await result.current.refreshHermesConfig() + }) + + // The configured terminal.cwd must override the stale localStorage value + expect($currentCwd.get()).toBe('/Users/example/new-workspace') + }) + + it('uses empty string when terminal.cwd is not set and localStorage is empty', async () => { + vi.mocked(getHermesConfig).mockResolvedValue({} as any) + + const { result } = renderHook(() => + useHermesConfig({ + activeSessionIdRef: { current: null }, + refreshProjectBranch: vi.fn().mockResolvedValue(undefined), + }), + ) + + await act(async () => { + await result.current.refreshHermesConfig() + }) + + expect($currentCwd.get()).toBe('') + }) + + it('ignores terminal.cwd when it is "."', async () => { + vi.mocked(getHermesConfig).mockResolvedValue({ + terminal: { cwd: '.' }, + } as any) + + const { result } = renderHook(() => + useHermesConfig({ + activeSessionIdRef: { current: null }, + refreshProjectBranch: vi.fn().mockResolvedValue(undefined), + }), + ) + + await act(async () => { + await result.current.refreshHermesConfig() + }) + + expect($currentCwd.get()).toBe('') + }) + + it('calls refreshProjectBranch with the configured cwd', async () => { + const refreshProjectBranch = vi.fn().mockResolvedValue(undefined) + setCurrentCwd('') + + vi.mocked(getHermesConfig).mockResolvedValue({ + terminal: { cwd: '/workspace/project-a' }, + } as any) + + const { result } = renderHook(() => + useHermesConfig({ + activeSessionIdRef: { current: null }, + refreshProjectBranch, + }), + ) + + await act(async () => { + await result.current.refreshHermesConfig() + }) + + expect(refreshProjectBranch).toHaveBeenCalledWith('/workspace/project-a') + }) +}) \ No newline at end of file diff --git a/apps/desktop/src/app/session/hooks/use-hermes-config.ts b/apps/desktop/src/app/session/hooks/use-hermes-config.ts index 84bff0e59..2ebe5afff 100644 --- a/apps/desktop/src/app/session/hooks/use-hermes-config.ts +++ b/apps/desktop/src/app/session/hooks/use-hermes-config.ts @@ -3,7 +3,6 @@ import { type MutableRefObject, useCallback, useState } from 'react' import { getHermesConfig, getHermesConfigDefaults } from '@/hermes' import { BUILTIN_PERSONALITIES, normalizePersonalityValue, personalityNamesFromConfig } from '@/lib/chat-runtime' import { - $currentCwd, setAvailablePersonalities, setCurrentCwd, setCurrentFastMode, @@ -53,8 +52,8 @@ export function useHermesConfig({ activeSessionIdRef, refreshProjectBranch }: He const cwd = (config.terminal?.cwd ?? '').trim() if (cwd && cwd !== '.') { - setCurrentCwd(prev => prev || cwd) - void refreshProjectBranch($currentCwd.get() || cwd) + setCurrentCwd(cwd) + void refreshProjectBranch(cwd) } const reasoning = (config.agent?.reasoning_effort ?? '').trim()