Fix file browser absolute path copy (#860)
This commit is contained in:
@@ -3,6 +3,7 @@ import { request, getApiKey, getBaseUrlValue } from '../client'
|
||||
export interface FileEntry {
|
||||
name: string
|
||||
path: string
|
||||
absolutePath?: string
|
||||
isDir: boolean
|
||||
size: number
|
||||
modTime: string
|
||||
@@ -11,13 +12,14 @@ export interface FileEntry {
|
||||
export interface FileStat {
|
||||
name: string
|
||||
path: string
|
||||
absolutePath?: string
|
||||
isDir: boolean
|
||||
size: number
|
||||
modTime: string
|
||||
permissions?: string
|
||||
}
|
||||
|
||||
export async function listFiles(path: string = ''): Promise<{ entries: FileEntry[]; path: string }> {
|
||||
export async function listFiles(path: string = ''): Promise<{ entries: FileEntry[]; path: string; absolutePath?: string }> {
|
||||
const params = new URLSearchParams()
|
||||
if (path) params.set('path', path)
|
||||
const query = params.toString()
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useFilesStore, isTextFile, isImageFile, isMarkdownFile } from '@/stores
|
||||
import { downloadFile } from '@/api/hermes/download'
|
||||
import type { FileEntry } from '@/api/hermes/files'
|
||||
import { copyToClipboard } from '@/utils/clipboard'
|
||||
import { getClipboardPathForEntry } from '@/utils/file-path'
|
||||
|
||||
const { t } = useI18n()
|
||||
const message = useMessage()
|
||||
@@ -74,7 +75,7 @@ async function handleSelect(key: string) {
|
||||
try { await downloadFile(entry.path, entry.name) } catch (err: any) { message.error(err.message) }
|
||||
break
|
||||
case 'copyPath': {
|
||||
const ok = await copyToClipboard(entry.path)
|
||||
const ok = await copyToClipboard(getClipboardPathForEntry(entry))
|
||||
if (ok) {
|
||||
message.success(t('files.pathCopied'))
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { FileEntry } from '@/api/hermes/files'
|
||||
|
||||
export function getClipboardPathForEntry(entry: FileEntry): string {
|
||||
return entry.absolutePath || entry.path
|
||||
}
|
||||
@@ -6,6 +6,10 @@ import {
|
||||
MAX_EDIT_SIZE,
|
||||
} from '../../services/hermes/file-provider'
|
||||
|
||||
function withAbsolutePath<T extends { path: string }>(entry: T): T & { absolutePath: string } {
|
||||
return { ...entry, absolutePath: resolveHermesPath(entry.path) }
|
||||
}
|
||||
|
||||
export const fileRoutes = new Router()
|
||||
|
||||
function handleError(ctx: any, err: any) {
|
||||
@@ -39,7 +43,7 @@ fileRoutes.get('/api/hermes/files/list', async (ctx) => {
|
||||
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1
|
||||
return a.name.localeCompare(b.name)
|
||||
})
|
||||
ctx.body = { entries, path: relativePath }
|
||||
ctx.body = { entries: entries.map(withAbsolutePath), path: relativePath, absolutePath: absPath }
|
||||
} catch (err: any) {
|
||||
handleError(ctx, err)
|
||||
}
|
||||
@@ -57,7 +61,7 @@ fileRoutes.get('/api/hermes/files/stat', async (ctx) => {
|
||||
const absPath = resolveHermesPath(relativePath)
|
||||
const provider = await createFileProvider()
|
||||
const info = await provider.stat(absPath)
|
||||
ctx.body = info
|
||||
ctx.body = withAbsolutePath(info)
|
||||
} catch (err: any) {
|
||||
handleError(ctx, err)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { WebSocketServer } from 'ws'
|
||||
import type { Server as HttpServer } from 'http'
|
||||
import { accessSync, chmodSync, constants as fsConstants, existsSync } from 'fs'
|
||||
import { dirname, join } from 'path'
|
||||
import { dirname, join, isAbsolute, resolve as resolvePath } from 'path'
|
||||
import { homedir } from 'os'
|
||||
import { getActiveProfileDir } from '../../services/hermes/hermes-profile'
|
||||
import { getTerminalConfig, type TerminalConfig } from '../../services/hermes/file-provider'
|
||||
import { getToken } from '../../services/auth'
|
||||
import { logger } from '../../services/logger'
|
||||
|
||||
@@ -66,6 +68,22 @@ function shellName(shell: string): string {
|
||||
return shell.split('/').pop() || 'shell'
|
||||
}
|
||||
|
||||
export function resolveTerminalCwd(
|
||||
cfg: Pick<TerminalConfig, 'cwd'> = getTerminalConfig(),
|
||||
profileDir = getActiveProfileDir(),
|
||||
): string {
|
||||
const configured = cfg.cwd?.trim()
|
||||
const fallback = existsSync(profileDir) ? profileDir : homedir()
|
||||
if (!configured) return fallback
|
||||
|
||||
const cwd = isAbsolute(configured) ? configured : resolvePath(profileDir, configured)
|
||||
if (!existsSync(cwd)) {
|
||||
logger.warn({ cwd }, 'Configured terminal cwd does not exist; falling back to Hermes profile directory')
|
||||
return fallback
|
||||
}
|
||||
return cwd
|
||||
}
|
||||
|
||||
// ─── Session types ──────────────────────────────────────────────
|
||||
|
||||
interface PtySession {
|
||||
@@ -96,7 +114,7 @@ function createSession(shell: string): PtySession {
|
||||
name: 'xterm-color',
|
||||
cols: 80,
|
||||
rows: 24,
|
||||
cwd: homedir(),
|
||||
cwd: resolveTerminalCwd(),
|
||||
})
|
||||
} catch (err: any) {
|
||||
throw new Error(`Failed to spawn shell "${shell}": ${err.message}`)
|
||||
|
||||
Reference in New Issue
Block a user