mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-01 12:02:05 +00:00
fix(desktop): make project "Add folder" picker remote-gateway aware
The new-project / add-folder dialog (PR #49037) picked folders via the native Electron dialog (pickDefaultProjectDir), which only browses the LOCAL machine. On a remote gateway that picks a path that doesn't exist on the backend where sessions actually run. Route pickProjectFolder() through selectDesktopPaths({directories, multiple:false}) — the same remote-aware path the retired right-sidebar picker used: local mode opens the native directory dialog, remote mode browses the backend filesystem via the in-app RemoteFolderPicker. Seed it with the backend's default cwd on remote so it opens somewhere useful.
This commit is contained in:
parent
b699d27a4a
commit
4526fccdbe
2 changed files with 58 additions and 11 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import {
|
||||
$projectScope,
|
||||
|
|
@ -6,9 +6,21 @@ import {
|
|||
ALL_PROJECTS,
|
||||
enterProject,
|
||||
exitProjectScope,
|
||||
pickProjectFolder,
|
||||
refreshWorktrees
|
||||
} from './projects'
|
||||
|
||||
vi.mock('@/lib/desktop-fs', () => ({
|
||||
desktopDefaultCwd: vi.fn(),
|
||||
isDesktopFsRemoteMode: vi.fn(),
|
||||
selectDesktopPaths: vi.fn()
|
||||
}))
|
||||
|
||||
const fs = await import('@/lib/desktop-fs')
|
||||
const desktopDefaultCwd = vi.mocked(fs.desktopDefaultCwd)
|
||||
const isDesktopFsRemoteMode = vi.mocked(fs.isDesktopFsRemoteMode)
|
||||
const selectDesktopPaths = vi.mocked(fs.selectDesktopPaths)
|
||||
|
||||
describe('project scope', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear()
|
||||
|
|
@ -50,3 +62,38 @@ describe('worktree refresh', () => {
|
|||
expect($worktreeRefreshToken.get()).toBe(before + 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('pickProjectFolder', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('uses the remote-aware directory picker locally (no backend default cwd probe)', async () => {
|
||||
isDesktopFsRemoteMode.mockReturnValue(false)
|
||||
selectDesktopPaths.mockResolvedValue(['/local/repo'])
|
||||
|
||||
await expect(pickProjectFolder()).resolves.toBe('/local/repo')
|
||||
expect(selectDesktopPaths).toHaveBeenCalledWith({ defaultPath: undefined, directories: true, multiple: false })
|
||||
expect(desktopDefaultCwd).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('seeds the picker with the backend cwd on a remote gateway', async () => {
|
||||
isDesktopFsRemoteMode.mockReturnValue(true)
|
||||
desktopDefaultCwd.mockResolvedValue({ branch: 'main', cwd: '/backend/work' })
|
||||
selectDesktopPaths.mockResolvedValue(['/backend/work/repo'])
|
||||
|
||||
await expect(pickProjectFolder()).resolves.toBe('/backend/work/repo')
|
||||
expect(selectDesktopPaths).toHaveBeenCalledWith({
|
||||
defaultPath: '/backend/work',
|
||||
directories: true,
|
||||
multiple: false
|
||||
})
|
||||
})
|
||||
|
||||
it('returns null when the picker is cancelled (empty selection)', async () => {
|
||||
isDesktopFsRemoteMode.mockReturnValue(false)
|
||||
selectDesktopPaths.mockResolvedValue([])
|
||||
|
||||
await expect(pickProjectFolder()).resolves.toBeNull()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { atom } from 'nanostores'
|
|||
|
||||
import { liveSessionProjectId, type SidebarProjectTree } from '@/app/chat/sidebar/projects/workspace-groups'
|
||||
import type { HermesGitBranch } from '@/global'
|
||||
import { desktopDefaultCwd, isDesktopFsRemoteMode, selectDesktopPaths } from '@/lib/desktop-fs'
|
||||
import { persistentAtom } from '@/lib/persisted'
|
||||
import { activeGateway, ensureActiveGatewayOpen } from '@/store/gateway'
|
||||
import { setSidebarAgentsGrouped } from '@/store/layout'
|
||||
|
|
@ -732,19 +733,18 @@ export async function copyPath(path: null | string): Promise<void> {
|
|||
}
|
||||
}
|
||||
|
||||
// Open the native directory picker (reuses the Electron default-project-dir
|
||||
// chooser). Returns the chosen absolute path, or null when cancelled.
|
||||
// Pick a folder for a project. Routes through the remote-aware folder picker
|
||||
// (selectDesktopPaths): a remote gateway browses the BACKEND filesystem via the
|
||||
// in-app RemoteFolderPicker — where sessions actually run — while local mode
|
||||
// uses the native directory dialog. Returns the chosen absolute path, or null
|
||||
// when cancelled. Seeded with the backend's default cwd on remote so the picker
|
||||
// opens somewhere useful instead of "/".
|
||||
export async function pickProjectFolder(): Promise<null | string> {
|
||||
const pick = window.hermesDesktop?.settings?.pickDefaultProjectDir
|
||||
|
||||
if (!pick) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await pick()
|
||||
const defaultPath = isDesktopFsRemoteMode() ? (await desktopDefaultCwd())?.cwd : undefined
|
||||
const [dir] = await selectDesktopPaths({ defaultPath, directories: true, multiple: false })
|
||||
|
||||
return result.canceled ? null : result.dir
|
||||
return dir || null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue