mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-22 10:32:00 +00:00
Group recents as parent-repo → worktree → sessions using local git metadata (probed over IPC, with a path-name heuristic fallback for remote backends). Single-worktree repos collapse to one level. Sessions order by creation time and never reshuffle on new messages. Also: fuse the status stack to the composer border, restore icon actions in the queue panel, fix sidebar label truncation and drag styling, hide sticky-message attachments while pinned, and bump the terminal font.
113 lines
3.4 KiB
TypeScript
113 lines
3.4 KiB
TypeScript
import type {
|
|
HermesConnection,
|
|
HermesReadDirResult,
|
|
HermesReadFileTextResult,
|
|
HermesSelectPathsOptions,
|
|
HermesWorktreeInfo
|
|
} from '@/global'
|
|
import { $connection } from '@/store/session'
|
|
|
|
export interface DesktopFsRemotePicker {
|
|
selectPaths: (options?: HermesSelectPathsOptions) => Promise<string[]>
|
|
}
|
|
|
|
let remotePicker: DesktopFsRemotePicker | null = null
|
|
|
|
export function setDesktopFsRemotePicker(next: DesktopFsRemotePicker | null) {
|
|
remotePicker = next
|
|
}
|
|
|
|
function connectionCacheKey(connection: HermesConnection | null) {
|
|
if (!connection) {
|
|
return 'local:'
|
|
}
|
|
return `${connection.mode || 'local'}:${connection.profile || ''}:${connection.baseUrl || ''}`
|
|
}
|
|
|
|
export function desktopFsCacheKey() {
|
|
return connectionCacheKey($connection.get())
|
|
}
|
|
|
|
export function isDesktopFsRemoteMode() {
|
|
return $connection.get()?.mode === 'remote'
|
|
}
|
|
|
|
function fsPath(endpoint: string, filePath: string) {
|
|
return `/api/fs/${endpoint}?path=${encodeURIComponent(filePath)}`
|
|
}
|
|
|
|
function bridge() {
|
|
const desktop = window.hermesDesktop
|
|
if (!desktop) {
|
|
throw new Error('Hermes Desktop bridge is unavailable')
|
|
}
|
|
return desktop
|
|
}
|
|
|
|
export async function readDesktopDir(path: string): Promise<HermesReadDirResult> {
|
|
const desktop = bridge()
|
|
if (!isDesktopFsRemoteMode()) {
|
|
return desktop.readDir(path)
|
|
}
|
|
return desktop.api<HermesReadDirResult>({ path: fsPath('list', path) })
|
|
}
|
|
|
|
export async function readDesktopFileText(path: string): Promise<HermesReadFileTextResult> {
|
|
const desktop = bridge()
|
|
if (!isDesktopFsRemoteMode()) {
|
|
return desktop.readFileText(path)
|
|
}
|
|
return desktop.api<HermesReadFileTextResult>({ path: fsPath('read-text', path) })
|
|
}
|
|
|
|
export async function readDesktopFileDataUrl(path: string): Promise<string> {
|
|
const desktop = bridge()
|
|
if (!isDesktopFsRemoteMode()) {
|
|
return desktop.readFileDataUrl(path)
|
|
}
|
|
|
|
const result = await desktop.api<string | { dataUrl?: string }>({ path: fsPath('read-data-url', path) })
|
|
return typeof result === 'string' ? result : result.dataUrl || ''
|
|
}
|
|
|
|
export async function desktopGitRoot(path: string): Promise<string | null> {
|
|
const desktop = bridge()
|
|
if (!isDesktopFsRemoteMode()) {
|
|
return desktop.gitRoot ? desktop.gitRoot(path) : null
|
|
}
|
|
|
|
const result = await desktop.api<{ root: string | null }>({ path: fsPath('git-root', path) })
|
|
return result.root
|
|
}
|
|
|
|
// Worktree detection runs against the LOCAL filesystem (the electron main
|
|
// process). For a remote backend the session cwds live on another machine, so
|
|
// we can't resolve them here — callers fall back to the path-name heuristic.
|
|
export async function desktopWorktrees(cwds: string[]): Promise<Record<string, HermesWorktreeInfo | null>> {
|
|
if (isDesktopFsRemoteMode()) {
|
|
return {}
|
|
}
|
|
|
|
const desktop = bridge()
|
|
|
|
return desktop.worktrees ? desktop.worktrees(cwds) : {}
|
|
}
|
|
|
|
export async function desktopDefaultCwd(): Promise<{ branch: string; cwd: string } | null> {
|
|
if (!isDesktopFsRemoteMode()) {
|
|
return null
|
|
}
|
|
|
|
return bridge().api<{ branch: string; cwd: string }>({ path: '/api/fs/default-cwd' })
|
|
}
|
|
|
|
export async function selectDesktopPaths(options?: HermesSelectPathsOptions): Promise<string[]> {
|
|
const desktop = bridge()
|
|
if (!isDesktopFsRemoteMode()) {
|
|
return desktop.selectPaths(options)
|
|
}
|
|
if (!options?.directories || options.multiple !== false) {
|
|
return []
|
|
}
|
|
return remotePicker ? remotePicker.selectPaths(options) : []
|
|
}
|