chore: 保存 Agent 安全优化前基线

This commit is contained in:
Logan.Li committed 2026-09-02 23:31:38 +08:00
1 parent 08696896f9
commit ff016347cd
116 files changed
+3858 -2485

No files matched your search

File diff suppressed because it is too large. Load diff
+25 -38
View File
@@ -10,22 +10,19 @@ import { openLocalShellTab, type ShellOption } from '../layout/sidebar/LocalShel
import appIconUrl from '../../assets/opsxshell-app-icon.png'
import { shellDisplayFromPath } from '../../utils/shellName'
import { fallbackLocalShells, modKeyLabel } from '../../utils/platformShells'
import {
buildOpenTabPayload,
defaultPortForProtocol,
sessionProtocol,
} from '../../utils/sessionProtocol'
import { buildOpenTabPayload, defaultPortForProtocol, sessionProtocol } from '../../utils/sessionProtocol'
interface WelcomeViewProps {
onNewSession?: () => void
onQuickConnect?: () => void
onRdpConnect?: () => void
onVncConnect?: () => void
onImportSessions?: () => void
}
function Kbd({ children }: { children: string }) {
return (
<kbd className="rounded border border-dark-600/80 bg-dark-900/80 px-1.5 py-0.5 font-mono text-[10px] font-medium text-txt-faint">
<kbd className="border-dark-600/80 bg-dark-900/80 rounded border px-1.5 py-0.5 font-mono text-[10px] font-medium text-txt-faint">
{children}
</kbd>
)
@@ -36,6 +33,7 @@ export default function WelcomeView({
onQuickConnect,
onRdpConnect,
onVncConnect,
onImportSessions,
}: WelcomeViewProps) {
const { t } = useTranslation('sessions')
const { addTab } = useTabStore()
@@ -71,15 +69,11 @@ export default function WelcomeView({
}, [shellMenuOpen])
const defaultShell = shells.find((s) => s.isDefault) || shells[0]
const defaultShellLabel = defaultShell
? shellDisplayFromPath(defaultShell.path || defaultShell.name).title
: 'Shell'
const defaultShellLabel = defaultShell ? shellDisplayFromPath(defaultShell.path || defaultShell.name).title : 'Shell'
const openDefaultLocal = useCallback(() => {
openLocalShellTab(
defaultShell
? { path: defaultShell.path, kind: defaultShell.kind, name: defaultShell.name }
: undefined
defaultShell ? { path: defaultShell.path, kind: defaultShell.kind, name: defaultShell.name } : undefined
)
}, [defaultShell])
@@ -112,7 +106,7 @@ export default function WelcomeView({
<button
type="button"
onClick={() => onQuickConnect?.()}
className="group flex flex-col gap-4 rounded-xl border border-dark-700/60 bg-dark-800/50 p-4 text-left transition-colors hover:border-accent-blue/35 hover:bg-dark-800"
className="border-dark-700/60 bg-dark-800/50 group flex flex-col gap-4 rounded-xl border p-4 text-left transition-colors hover:border-accent-blue/35 hover:bg-dark-800"
>
<div className="flex items-center justify-between">
<span className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent-blue/15 text-accent-blue">
@@ -129,7 +123,7 @@ export default function WelcomeView({
<button
type="button"
onClick={() => onNewSession?.()}
className="group flex flex-col gap-4 rounded-xl border border-dark-700/60 bg-dark-800/50 p-4 text-left transition-colors hover:border-accent-green/35 hover:bg-dark-800"
className="border-dark-700/60 bg-dark-800/50 group flex flex-col gap-4 rounded-xl border p-4 text-left transition-colors hover:border-accent-green/35 hover:bg-dark-800"
>
<div className="flex items-center justify-between">
<span className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent-green/15 text-accent-green">
@@ -144,7 +138,7 @@ export default function WelcomeView({
</button>
<div ref={shellMenuRef} className="relative">
<div className="flex h-full overflow-hidden rounded-xl border border-dark-700/60 bg-dark-800/50 transition-colors hover:border-dark-600 hover:bg-dark-800">
<div className="border-dark-700/60 bg-dark-800/50 flex h-full overflow-hidden rounded-xl border transition-colors hover:border-dark-600 hover:bg-dark-800">
<button
type="button"
onClick={openDefaultLocal}
@@ -158,9 +152,7 @@ export default function WelcomeView({
</div>
<div>
<div className="text-sm font-medium text-content-primary">{t('welcome.localShell.title')}</div>
<div className="mt-1 truncate text-xs leading-relaxed text-txt-muted">
{defaultShellLabel}
</div>
<div className="mt-1 truncate text-xs leading-relaxed text-txt-muted">{defaultShellLabel}</div>
</div>
</button>
<button
@@ -168,14 +160,14 @@ export default function WelcomeView({
aria-label={t('welcome.localShell.selectShell')}
aria-expanded={shellMenuOpen}
onClick={() => setShellMenuOpen((v) => !v)}
className="flex w-9 flex-shrink-0 items-center justify-center border-l border-dark-700/60 text-txt-faint transition-colors hover:bg-dark-700/40 hover:text-content-secondary"
className="border-dark-700/60 hover:bg-dark-700/40 flex w-9 flex-shrink-0 items-center justify-center border-l text-txt-faint transition-colors hover:text-content-secondary"
>
<ChevronRight className={`h-4 w-4 transition-transform ${shellMenuOpen ? 'rotate-90' : ''}`} />
</button>
</div>
{shellMenuOpen && shells.length > 0 && (
<div className="absolute left-0 right-0 top-[calc(100%+6px)] z-50 overflow-hidden rounded-xl border border-dark-600/80 bg-dark-800 py-1 shadow-xl">
<div className="border-dark-600/80 absolute left-0 right-0 top-[calc(100%+6px)] z-50 overflow-hidden rounded-xl border bg-dark-800 py-1 shadow-xl">
{shells.map((s) => (
<button
key={s.path}
@@ -184,7 +176,7 @@ export default function WelcomeView({
openLocalShellTab({ path: s.path, kind: s.kind, name: s.name })
setShellMenuOpen(false)
}}
className="flex w-full items-center gap-2.5 px-3 py-2 text-left transition-colors hover:bg-dark-700/70"
className="hover:bg-dark-700/70 flex w-full items-center gap-2.5 px-3 py-2 text-left transition-colors"
>
<span className="w-10 font-mono text-[10px] uppercase text-txt-faint">{s.kind}</span>
<span className="flex-1 text-sm text-content-primary">{s.name}</span>
@@ -201,7 +193,9 @@ export default function WelcomeView({
<section aria-label={t('welcome.sectionDesktop')} className="mb-10">
<div className="mb-3 flex items-center gap-2">
<h2 className="text-[11px] font-semibold uppercase tracking-wider text-txt-faint">{t('welcome.sectionDesktop')}</h2>
<h2 className="text-[11px] font-semibold uppercase tracking-wider text-txt-faint">
{t('welcome.sectionDesktop')}
</h2>
</div>
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<button
@@ -210,7 +204,7 @@ export default function WelcomeView({
if (!requirePro('rdp')) return
onRdpConnect?.()
}}
className="flex items-center gap-3 rounded-xl border border-dark-700/50 bg-dark-800/30 px-4 py-3 text-left transition-colors hover:border-accent-blue/40"
className="border-dark-700/50 bg-dark-800/30 flex items-center gap-3 rounded-xl border px-4 py-3 text-left transition-colors hover:border-accent-blue/40"
>
<span className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent-blue/15 text-accent-blue">
<Monitor className="h-4 w-4" />
@@ -226,7 +220,7 @@ export default function WelcomeView({
if (!requirePro('vnc')) return
onVncConnect?.()
}}
className="flex items-center gap-3 rounded-xl border border-dark-700/50 bg-dark-800/30 px-4 py-3 text-left transition-colors hover:border-accent-blue/40"
className="border-dark-700/50 bg-dark-800/30 flex items-center gap-3 rounded-xl border px-4 py-3 text-left transition-colors hover:border-accent-blue/40"
>
<span className="flex h-9 w-9 items-center justify-center rounded-lg bg-accent-blue/15 text-accent-blue">
<Cast className="h-4 w-4" />
@@ -245,34 +239,29 @@ export default function WelcomeView({
<h2 className="text-[11px] font-semibold uppercase tracking-wider text-txt-faint">
{t('welcome.sectionRecent')}
</h2>
{recentSessions.length > 0 && (
<span className="text-[11px] text-txt-dim">{recentSessions.length}</span>
)}
{recentSessions.length > 0 && <span className="text-[11px] text-txt-dim">{recentSessions.length}</span>}
</div>
{recentSessions.length === 0 ? (
<div className="rounded-xl border border-dashed border-dark-700/70 px-4 py-10">
<div className="border-dark-700/70 rounded-xl border border-dashed px-4 py-10">
<EmptyState
icon={Server}
title={t('welcome.recentEmpty.title')}
description={t('welcome.recentEmpty.desc')}
action={onImportSessions ? { label: t('welcome.import.title'), onClick: onImportSessions } : undefined}
/>
</div>
) : (
<ul className="divide-y divide-dark-700/40 overflow-hidden rounded-xl border border-dark-700/50">
<ul className="divide-dark-700/40 border-dark-700/50 divide-y overflow-hidden rounded-xl border">
{recentSessions.map((session) => (
<li key={session.id}>
<button
type="button"
onClick={() => handleSessionClick(session)}
className="group flex w-full items-center gap-3 px-3.5 py-2.5 text-left transition-colors hover:bg-dark-800/80"
className="hover:bg-dark-800/80 group flex w-full items-center gap-3 px-3.5 py-2.5 text-left transition-colors"
>
<span className="flex h-8 w-8 flex-shrink-0 items-center justify-center">
<HostDistroIcon
distro={session.distro}
protocol={session.protocol}
size="md"
/>
<HostDistroIcon distro={session.distro} protocol={session.protocol} size="md" />
</span>
<span className="min-w-0 flex-1">
<span className="block truncate text-sm text-content-primary">{session.name}</span>
@@ -282,9 +271,7 @@ export default function WelcomeView({
</span>
</span>
{session.group ? (
<span className="hidden flex-shrink-0 text-[11px] text-txt-dim sm:inline">
{session.group}
</span>
<span className="hidden flex-shrink-0 text-[11px] text-txt-dim sm:inline">{session.group}</span>
) : null}
<ChevronRight className="h-3.5 w-3.5 flex-shrink-0 text-txt-dim opacity-0 transition-opacity group-hover:opacity-100" />
</button>