@burdenoff/microfe-vibecontrols 2026.521.3 → 2026.522.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/VibeControlsRoot.js +86 -78
- package/dist/VibeControlsRoot.js.map +1 -1
- package/dist/VibeControlsRoutes.js +168 -125
- package/dist/VibeControlsRoutes.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerBookmarksDrawer.js +174 -0
- package/dist/components/agent-manager/AgentManagerBookmarksDrawer.js.map +1 -0
- package/dist/components/agent-manager/AgentManagerChatPane.js +149 -94
- package/dist/components/agent-manager/AgentManagerChatPane.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerMessageItem.js +52 -41
- package/dist/components/agent-manager/AgentManagerMessageItem.js.map +1 -1
- package/dist/components/agent-manager/AgentManagerMessageList.js +22 -15
- package/dist/components/agent-manager/AgentManagerMessageList.js.map +1 -1
- package/dist/components/agents/OpenInEditorMenu.js +241 -0
- package/dist/components/agents/OpenInEditorMenu.js.map +1 -0
- package/dist/components/agents/VibeOpenInEditorMenu.js +20 -0
- package/dist/components/agents/VibeOpenInEditorMenu.js.map +1 -0
- package/dist/components/agents/idePresets.js +148 -0
- package/dist/components/agents/idePresets.js.map +1 -0
- package/dist/components/agents/index.js +3 -0
- package/dist/components/ai/AIPlanPanel.js +332 -0
- package/dist/components/ai/AIPlanPanel.js.map +1 -0
- package/dist/components/analytics/index.js +2 -2
- package/dist/components/assistant/AssistantMessageItem.js +55 -47
- package/dist/components/assistant/AssistantMessageItem.js.map +1 -1
- package/dist/components/audit/AuditExportButton.js +87 -41
- package/dist/components/audit/AuditExportButton.js.map +1 -1
- package/dist/components/gitops/CIDurationChart.js +11 -11
- package/dist/components/security/SecurityEmptyState.js +33 -0
- package/dist/components/security/SecurityEmptyState.js.map +1 -0
- package/dist/components/security/SecurityEvidenceList.js +42 -0
- package/dist/components/security/SecurityEvidenceList.js.map +1 -0
- package/dist/components/security/SecurityFindingsTable.js +201 -0
- package/dist/components/security/SecurityFindingsTable.js.map +1 -0
- package/dist/components/security/SecurityHeaderStrip.js +67 -0
- package/dist/components/security/SecurityHeaderStrip.js.map +1 -0
- package/dist/components/security/SecurityLifecycleStepper.js +66 -0
- package/dist/components/security/SecurityLifecycleStepper.js.map +1 -0
- package/dist/components/security/SecurityProviderDrawer.js +112 -0
- package/dist/components/security/SecurityProviderDrawer.js.map +1 -0
- package/dist/components/security/SecurityTabPanel.js +105 -0
- package/dist/components/security/SecurityTabPanel.js.map +1 -0
- package/dist/components/security/gql.js +128 -0
- package/dist/components/security/gql.js.map +1 -0
- package/dist/components/security/index.js +8 -0
- package/dist/components/security/types.js +80 -0
- package/dist/components/security/types.js.map +1 -0
- package/dist/components/settings/IdePreferencesSection.js +66 -0
- package/dist/components/settings/IdePreferencesSection.js.map +1 -0
- package/dist/components/shared/PageSkeleton.js +88 -0
- package/dist/components/shared/PageSkeleton.js.map +1 -0
- package/dist/constants/pluginCatalog.js +20 -8
- package/dist/constants/pluginCatalog.js.map +1 -1
- package/dist/generated/wspace-operations.js +1350 -1262
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/hooks/useToggleAgentBookmark.js +32 -0
- package/dist/hooks/useToggleAgentBookmark.js.map +1 -0
- package/dist/index.js +10 -10
- package/dist/pages/AgentDetailsPage.js +25 -25
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/AgentsPage.js +326 -327
- package/dist/pages/AgentsPage.js.map +1 -1
- package/dist/pages/AnalyticsPage.js +425 -420
- package/dist/pages/AnalyticsPage.js.map +1 -1
- package/dist/pages/CatalogDetailPage.js +258 -249
- package/dist/pages/CatalogDetailPage.js.map +1 -1
- package/dist/pages/CatalogPage.js +22 -22
- package/dist/pages/CatalogPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +30 -30
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/ComponentsPage.js +23 -23
- package/dist/pages/ComponentsPage.js.map +1 -1
- package/dist/pages/LogsPage.js +107 -0
- package/dist/pages/LogsPage.js.map +1 -0
- package/dist/pages/NoteDetailsPage.js +12 -12
- package/dist/pages/NoteDetailsPage.js.map +1 -1
- package/dist/pages/SessionDetailsPage.js +12 -12
- package/dist/pages/SessionDetailsPage.js.map +1 -1
- package/dist/pages/SessionsPage.js +158 -136
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/pages/SettingsPage.js +60 -52
- package/dist/pages/SettingsPage.js.map +1 -1
- package/dist/pages/TargetDetailsPage.js +18 -18
- package/dist/pages/TargetDetailsPage.js.map +1 -1
- package/dist/pages/TargetsPage.js +328 -331
- package/dist/pages/TargetsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +17 -17
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/TemplatesPage.js +17 -17
- package/dist/pages/TemplatesPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +552 -535
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/VibesPage.js +321 -296
- package/dist/pages/VibesPage.js.map +1 -1
- package/dist/pages/ai/AIBookmarksPage.js +184 -0
- package/dist/pages/ai/AIBookmarksPage.js.map +1 -0
- package/dist/pages/ai/AIPage.js +138 -109
- package/dist/pages/ai/AIPage.js.map +1 -1
- package/dist/services/planApi.js +18 -0
- package/dist/services/planApi.js.map +1 -0
- package/dist/store/vibeControlsStore.js +20 -2
- package/dist/store/vibeControlsStore.js.map +1 -1
- package/dist/translations/en.js +30 -1
- package/dist/translations/en.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionDetailsPage.js","names":[],"sources":["../../src/pages/SessionDetailsPage.tsx"],"sourcesContent":["import { useState, useCallback, useEffect } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { useParams } from 'react-router-dom';\nimport { useVibeControlsStore } from '@/store/vibeControlsStore';\nimport {\n ArrowLeft,\n Terminal,\n Play,\n Square,\n RotateCcw,\n ExternalLink,\n Server,\n Zap,\n Clock,\n Folder,\n Code,\n Variable,\n Hash,\n RefreshCw,\n Loader2,\n AlertCircle,\n Maximize2,\n Minimize2,\n ChevronDown,\n ChevronUp,\n Pencil,\n Check,\n X,\n Tag,\n} from 'lucide-react';\nimport {\n PageHeader,\n Card,\n StatusBadge,\n EmptyState,\n LoadingState,\n ErrorState,\n ConfirmDialog,\n} from '@/components/shared';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport {\n useGetSessionQuery,\n useStartSessionMutation,\n useStopSessionMutation,\n useRestartSessionMutation,\n useStartSessionTerminalMutation,\n useRestartSessionTerminalMutation,\n useUpdateSessionMutation,\n} from '@/generated/wspace-operations';\nimport { getQuotaDialogContent, isQuotaExhaustedError } from '@/utils/quotaUtils';\n\n/**\n * Resolves the terminal URL for a session.\n * Each session gets its own ttyd instance + cloudflared tunnel.\n * The URL is set by the backend's startSessionTerminal mutation.\n */\nfunction getTerminalUrl(session: { ttydUrl?: string | null }): string | null {\n return session.ttydUrl || null;\n}\n\n/**\n * Session details page - shows comprehensive information about a single session\n * with an integrated terminal panel.\n */\nexport function SessionDetailsPage() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n const { id } = useParams<{ id: string }>();\n const { basePath: basePathProp } = useVibeControls();\n const basePath = basePathProp || '';\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n\n const [startSession] = useStartSessionMutation({ refetchQueries: ['GetSession'] });\n const [stopSession] = useStopSessionMutation({ refetchQueries: ['GetSession'] });\n const [restartSession] = useRestartSessionMutation({ refetchQueries: ['GetSession'] });\n const [startSessionTerminal] = useStartSessionTerminalMutation({\n refetchQueries: ['GetSession'],\n });\n const [restartSessionTerminal] = useRestartSessionTerminalMutation({\n refetchQueries: ['GetSession'],\n });\n const [updateSession] = useUpdateSessionMutation({ refetchQueries: ['GetSession'] });\n\n // Command/working-directory inline edit state\n const [editingCommand, setEditingCommand] = useState(false);\n const [editCommand, setEditCommand] = useState('');\n const [editWorkingDirectory, setEditWorkingDirectory] = useState('');\n const [editSaving, setEditSaving] = useState(false);\n\n const handleEditCommandOpen = () => {\n setEditCommand(session?.command || '');\n setEditWorkingDirectory(session?.workingDirectory || '');\n setEditingCommand(true);\n };\n\n const handleEditCommandSave = async () => {\n if (!session?.id) return;\n setEditSaving(true);\n try {\n await updateSession({\n variables: {\n id: session.id,\n input: {\n command: editCommand || null,\n workingDirectory: editWorkingDirectory || null,\n },\n },\n });\n setEditingCommand(false);\n } finally {\n setEditSaving(false);\n }\n };\n\n // Fetch session by ID from GraphQL API\n const { data, loading, error, refetch } = useGetSessionQuery({\n variables: { id: id || '' },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n // Get session from response\n const session = data?.session;\n\n // Get related agent and vibe from the session response\n const agent = session?.agent || null;\n const vibe = session?.vibe || null;\n\n // ── Sync active context ────────────────────────────────────────────────\n useEffect(() => {\n if (session) {\n useVibeControlsStore.setState({\n activeAgentId: (agent?.id as string) ?? null,\n selectedAgentId: (agent?.id as string) ?? null,\n activeVibeId: (vibe?.id as string) ?? null,\n selectedVibeId: (vibe?.id as string) ?? null,\n activeSessionId: session.id,\n selectedSessionId: session.id,\n });\n }\n }, [session?.id, agent?.id, vibe?.id]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Terminal state\n const [terminalOpen, setTerminalOpen] = useState(true);\n const [terminalMaximized, setTerminalMaximized] = useState(false);\n const [terminalLoading, setTerminalLoading] = useState(false);\n const [terminalError, setTerminalError] = useState<string | null>(null);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n\n const terminalUrl = session ? getTerminalUrl(session) : null;\n\n const handleBack = () => {\n navigate('/sessions');\n };\n\n const handleStartSession = async () => {\n if (!session?.id) return;\n try {\n await startSession({ variables: { id: session.id } });\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n console.error('Failed to start session:', err);\n }\n };\n\n const handleStopSession = async () => {\n if (!session?.id) return;\n try {\n await stopSession({ variables: { id: session.id } });\n } catch (err) {\n console.error('Failed to stop session:', err);\n }\n };\n\n const handleRestartSession = async () => {\n if (!session?.id) return;\n try {\n await restartSession({ variables: { id: session.id } });\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n console.error('Failed to restart session:', err);\n }\n };\n\n const handleStartTerminal = useCallback(async () => {\n if (!session) return;\n setTerminalLoading(true);\n setTerminalError(null);\n try {\n // Call the backend mutation which orchestrates agent API calls server-side\n // (creates tmux session, starts ttyd, starts cloudflared tunnel, saves ttydUrl)\n const result = await startSessionTerminal({ variables: { id: session.id } });\n if (result.error && isQuotaExhaustedError(result.error)) {\n setShowQuotaExhausted(true);\n } else if (result.error) {\n setTerminalError(result.error.message);\n } else if (!result.data?.startSessionTerminal) {\n setTerminalError('Failed to start terminal');\n } else {\n setTerminalOpen(true);\n }\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n const message = err instanceof Error ? err.message : 'Failed to start terminal';\n setTerminalError(message);\n } finally {\n setTerminalLoading(false);\n }\n }, [session, startSessionTerminal]);\n\n const handleRestartTerminal = useCallback(async () => {\n if (!session) return;\n setTerminalLoading(true);\n setTerminalError(null);\n try {\n const result = await restartSessionTerminal({ variables: { id: session.id } });\n if (result.error && isQuotaExhaustedError(result.error)) {\n setShowQuotaExhausted(true);\n } else if (result.error) {\n setTerminalError(result.error.message);\n } else if (!result.data?.restartSessionTerminal) {\n setTerminalError('Failed to restart terminal');\n } else {\n setTerminalOpen(true);\n }\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n const message = err instanceof Error ? err.message : 'Failed to restart terminal';\n setTerminalError(message);\n } finally {\n setTerminalLoading(false);\n }\n }, [session, restartSessionTerminal]);\n\n const handleOpenInNewTab = useCallback(() => {\n if (terminalUrl) {\n window.open(terminalUrl, '_blank');\n }\n }, [terminalUrl]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.loadingPermissions', 'Loading permissions...')}\n </p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.SESSION_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('sessionDetails.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'sessionDetails.accessDeniedDesc',\n \"You don't have permission to access this page.\"\n )}\n </p>\n </div>\n </div>\n );\n\n const handleAgentClick = () => {\n if (!agent) return;\n navigate(`/agents/${agent.id}`);\n };\n\n const handleVibeClick = () => {\n if (!vibe) return;\n navigate(`/vibes/${vibe.id}`);\n };\n\n const formatTimestamp = (timestamp: string | null | undefined) => {\n if (!timestamp) return 'Never';\n const diff = Date.now() - new Date(timestamp).getTime();\n if (diff < 60000) return 'Just now';\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;\n return new Date(timestamp).toLocaleDateString();\n };\n\n // Guard states wrapped in MotionPage to prevent unmount/remount animation replay\n if (loading && !session) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {tr('sessionDetails.backToSessions', 'Back to Sessions')}\n </button>\n <LoadingState message={tr('sessionDetails.loadingSession', 'Loading session details...')} />\n </MotionPage>\n );\n }\n\n if (error && !session) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n Back to Sessions\n </button>\n <ErrorState\n title={tr('sessionDetails.failedLoad', 'Failed to load session')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n if (!session) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n Back to Sessions\n </button>\n <EmptyState\n icon={<Terminal className=\"w-8 h-8 text-text-secondary\" />}\n title={tr('sessionDetails.notFound', 'Session not found')}\n description={`${tr('sessionDetails.notFoundDescPrefix', 'No session with ID')} \"${id}\" ${tr('sessionDetails.notFoundDescSuffix', 'exists')}`}\n action={\n <button\n onClick={handleBack}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('sessionDetails.backToSessions', 'Back to Sessions')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n const isRunning = session.status === 'RUNNING';\n const terminalHeight = terminalMaximized ? 'h-[calc(100vh-200px)]' : 'h-[280px] sm:h-[420px]';\n\n return (\n <MotionPage className=\"flex flex-col bg-bg-surface min-h-screen\">\n {/* Main content - scrollable */}\n <div\n className={`flex-1 overflow-y-auto space-y-6 p-4 sm:p-6 ${terminalOpen && terminalUrl ? 'pb-2' : ''}`}\n >\n {/* Back Button */}\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n Back to Sessions\n </button>\n\n {/* Header */}\n <PageHeader\n title={session.name}\n description={session.command || 'No command specified'}\n breadcrumb={[\n { label: 'Sessions', path: basePath ? `${basePath}/sessions` : '/sessions' },\n { label: session.name },\n ]}\n actions={\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title=\"Refresh\"\n >\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {isRunning ? (\n <>\n <button\n onClick={handleStopSession}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Square className=\"w-4 h-4\" />\n {tr('sessionDetails.stopCommand', 'Stop Command')}\n </button>\n <button\n onClick={handleRestartSession}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <RotateCcw className=\"w-4 h-4\" />\n {tr('sessionDetails.restartCommand', 'Restart Command')}\n </button>\n </>\n ) : (\n <button\n onClick={handleStartSession}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-success-bg text-status-success-text rounded-md hover:opacity-80 transition-colors\"\n >\n <Play className=\"w-4 h-4\" />\n {tr('sessionDetails.runCommand', 'Run Command')}\n </button>\n )}\n {/* Terminal toggle + open in new tab */}\n {terminalUrl ? (\n <>\n <button\n onClick={() => setTerminalOpen((prev) => !prev)}\n className={`flex items-center gap-2 px-3 py-2 rounded-md transition-colors ${\n terminalOpen\n ? 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover'\n : 'bg-bg-sunken text-text-primary hover:bg-bg-sunken/80'\n }`}\n title={\n terminalOpen\n ? tr('sessionDetails.hideTerminal', 'Hide terminal')\n : tr('sessionDetails.showTerminal', 'Show terminal')\n }\n >\n <Terminal className=\"w-4 h-4\" />\n {tr('sessionDetails.terminal', 'Terminal')}\n </button>\n <button\n onClick={handleRestartTerminal}\n disabled={terminalLoading}\n className=\"flex items-center px-2 py-2 bg-bg-sunken text-text-secondary rounded-md hover:text-text-primary hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={tr(\n 'sessionDetails.restartTerminalTitle',\n 'Restart terminal (new tunnel)'\n )}\n >\n {terminalLoading ? (\n <Loader2 className=\"w-3.5 h-3.5 animate-spin\" />\n ) : (\n <RotateCcw className=\"w-3.5 h-3.5\" />\n )}\n </button>\n <button\n onClick={handleOpenInNewTab}\n className=\"flex items-center px-2 py-2 bg-bg-sunken text-text-secondary rounded-md hover:text-text-primary hover:bg-bg-sunken/80 transition-colors\"\n title={tr('sessionDetails.openInNewTab', 'Open terminal in new tab')}\n >\n <ExternalLink className=\"w-4 h-4\" />\n </button>\n </>\n ) : (\n <button\n onClick={handleStartTerminal}\n disabled={terminalLoading || !agent}\n className=\"flex items-center gap-2 px-3 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n title={\n !agent\n ? tr('sessionDetails.noAgentAssigned', 'No agent assigned')\n : !agent.tunnelUrl\n ? tr(\n 'sessionDetails.agentNoTunnelUrl',\n 'Agent has no tunnel URL configured'\n )\n : tr('sessionDetails.openTerminal', 'Open terminal')\n }\n >\n {terminalLoading ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Terminal className=\"w-4 h-4\" />\n )}\n {tr('sessionDetails.openTerminal', 'Open Terminal')}\n </button>\n )}\n </div>\n }\n />\n\n {/* Status Cards */}\n <MotionList stagger={0.04} className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Terminal className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.statusLabel', 'Status')}\n </p>\n <StatusBadge status={session.status} size=\"md\" />\n </div>\n </div>\n </Card>\n </MotionItem>\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Code className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.typeLabel', 'Type')}\n </p>\n <p className=\"font-semibold text-text-primary\">{session.type}</p>\n </div>\n </div>\n </Card>\n </MotionItem>\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Hash className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.pidLabel', 'PID')}\n </p>\n <p className=\"font-semibold text-text-primary\">{session.pid || 'N/A'}</p>\n </div>\n </div>\n </Card>\n </MotionItem>\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.agentLabel', 'Agent')}\n </p>\n <p className=\"font-semibold text-text-primary truncate\">\n {agent?.name || 'Unknown'}\n </p>\n </div>\n </div>\n </Card>\n </MotionItem>\n </MotionList>\n\n {/* Command */}\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Code className=\"w-5 h-5\" />\n {tr('sessionDetails.commandTitle', 'Command')}\n </h3>\n {!editingCommand && (\n <button\n onClick={handleEditCommandOpen}\n className=\"p-1.5 rounded text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n title={tr('sessionDetails.editCommandTitle', 'Edit command and working directory')}\n >\n <Pencil className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n <div className=\"p-4\">\n {editingCommand ? (\n <div className=\"space-y-3\">\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n {tr('sessionDetails.commandLabel', 'Command')}\n </label>\n <input\n type=\"text\"\n value={editCommand}\n onChange={(e) => setEditCommand(e.target.value)}\n placeholder={tr('sessionDetails.commandPlaceholder', 'bun run dev')}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n autoFocus\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n {tr('sessionDetails.workingDirLabel', 'Working Directory')}\n </label>\n <input\n type=\"text\"\n value={editWorkingDirectory}\n onChange={(e) => setEditWorkingDirectory(e.target.value)}\n placeholder={tr('sessionDetails.workingDirPlaceholder', '/home/user/myproject')}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={handleEditCommandSave}\n disabled={editSaving}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {editSaving ? (\n <Loader2 className=\"w-3.5 h-3.5 animate-spin\" />\n ) : (\n <Check className=\"w-3.5 h-3.5\" />\n )}\n {tr('sessionDetails.save', 'Save')}\n </button>\n <button\n onClick={() => setEditingCommand(false)}\n disabled={editSaving}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50\"\n >\n <X className=\"w-3.5 h-3.5\" />\n {tr('sessionDetails.cancel', 'Cancel')}\n </button>\n </div>\n </div>\n ) : (\n <>\n <div className=\"bg-bg-sunken rounded-md p-3 font-mono text-sm text-text-primary overflow-x-auto\">\n ${' '}\n {session.command ||\n tr('sessionDetails.noCommandSpecified', 'No command specified')}\n </div>\n <div className=\"mt-3 flex items-center gap-2 text-sm text-text-secondary\">\n <Folder className=\"w-4 h-4\" />\n {tr('sessionDetails.workingDirectory', 'Working Directory')}:{' '}\n <span className=\"text-text-primary font-mono\">\n {session.workingDirectory || (\n <em className=\"not-italic text-text-placeholder\">\n {tr('sessionDetails.workingDirDefault', 'not set — defaults to OS home')}\n </em>\n )}\n </span>\n </div>\n </>\n )}\n </div>\n </Card>\n\n {/* Environment Variables */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Variable className=\"w-5 h-5\" />\n {tr('sessionDetails.envVars', 'Environment Variables')}\n </h3>\n </div>\n <div className=\"p-4\">\n {session.environmentVariables &&\n Object.keys(session.environmentVariables).length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {Object.entries(session.environmentVariables).map(([key, value]) => (\n <span\n key={key}\n className=\"px-3 py-1 bg-bg-sunken text-text-primary text-sm rounded-full font-mono\"\n >\n {key}={String(value)}\n </span>\n ))}\n </div>\n ) : (\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.noEnvVars', 'No environment variables configured')}\n </p>\n )}\n </div>\n </Card>\n\n {/* Last Output */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"w-5 h-5\" />\n {tr('sessionDetails.lastOutput', 'Last Output')}\n </h3>\n </div>\n <div className=\"p-4\">\n {session.lastOutput ? (\n <div className=\"bg-bg-sunken rounded-md p-3 font-mono text-sm text-text-primary overflow-x-auto whitespace-pre-wrap\">\n {session.lastOutput}\n </div>\n ) : (\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.noOutput', 'No output captured')}\n </p>\n )}\n </div>\n </Card>\n\n {/* Related Vibe */}\n {vibe && (\n <Card onClick={handleVibeClick} hoverable>\n <div className=\"p-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Zap className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.relatedVibe', 'Related Vibe')}\n </p>\n <p className=\"font-medium text-text-primary\">{vibe.name}</p>\n {vibe.path && (\n <p className=\"text-sm text-text-secondary truncate max-w-md\">{vibe.path}</p>\n )}\n </div>\n </div>\n <StatusBadge status={vibe.status} />\n </div>\n </Card>\n )}\n\n {/* Related Agent */}\n {agent && (\n <Card onClick={handleAgentClick} hoverable>\n <div className=\"p-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.runningOnAgent', 'Running on Agent')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.name}</p>\n <p className=\"text-sm text-text-secondary\">{agent.hostname}</p>\n </div>\n </div>\n <StatusBadge status={agent.isActive ? 'ACTIVE' : 'OFFLINE'} />\n </div>\n </Card>\n )}\n\n {/* Metadata */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Clock className=\"w-5 h-5\" />\n {tr('sessionDetails.timeline', 'Timeline')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.autoStart', 'Auto Start')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {session.autoStart\n ? tr('sessionDetails.yes', 'Yes')\n : tr('sessionDetails.no', 'No')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('sessionDetails.created', 'Created')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(session.createdAt)}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('sessionDetails.updated', 'Updated')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(session.updatedAt)}\n </p>\n </div>\n </div>\n {session.exitCode !== null && session.exitCode !== undefined && (\n <div className=\"mt-4 pt-4 border-t border-border-default\">\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.exitCode', 'Exit Code')}\n </p>\n <p\n className={`font-medium ${session.exitCode === 0 ? 'text-status-success-text' : 'text-status-error-text'}`}\n >\n {session.exitCode}\n </p>\n </div>\n )}\n </div>\n </Card>\n\n {/* Tags */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Tag className=\"w-5 h-5\" />\n {tr('sessionDetails.tags', 'Tags')}\n </h3>\n </div>\n <div className=\"p-4\">\n <EntityTagPicker entityType=\"VIBECONTROLS_SESSION\" entityId={session.id} />\n </div>\n </Card>\n </div>\n\n {/* Integrated Terminal Panel - docked at bottom */}\n {terminalOpen && (\n <div className=\"border-t border-border-default bg-bg-surface shrink-0\">\n {/* Terminal header bar */}\n <div className=\"flex items-center bg-bg-sunken border-b border-border-default\">\n <button\n onClick={() => setTerminalOpen(false)}\n className=\"flex items-center gap-1.5 px-3 py-2 text-text-secondary hover:text-text-primary transition-colors text-xs font-medium uppercase tracking-wide\"\n title={tr('sessionDetails.collapseTerminal', 'Collapse terminal')}\n >\n <Terminal className=\"w-3.5 h-3.5\" />\n {tr('sessionDetails.terminal', 'Terminal')}\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n <div className=\"flex items-center px-3 py-1.5 text-xs bg-bg-surface text-text-primary border-r border-border-subtle border-b-2 border-b-action-primary-bg\">\n <Terminal className=\"w-3 h-3 mr-1.5\" />\n {session.name}\n </div>\n <div className=\"flex-1\" />\n <div className=\"flex items-center gap-1 px-2\">\n {terminalUrl && (\n <button\n onClick={handleOpenInNewTab}\n className=\"p-1 text-text-secondary hover:text-text-primary transition-colors\"\n title={tr('sessionDetails.openInNewTabShort', 'Open in new tab')}\n >\n <ExternalLink className=\"w-3.5 h-3.5\" />\n </button>\n )}\n <button\n onClick={() => setTerminalMaximized((prev) => !prev)}\n className=\"p-1 text-text-secondary hover:text-text-primary transition-colors\"\n title={\n terminalMaximized\n ? tr('sessionDetails.restoreSize', 'Restore size')\n : tr('sessionDetails.maximize', 'Maximize')\n }\n >\n {terminalMaximized ? (\n <Minimize2 className=\"w-3.5 h-3.5\" />\n ) : (\n <Maximize2 className=\"w-3.5 h-3.5\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Terminal content */}\n <div className={`${terminalHeight} bg-bg-inverse text-text-inverse`}>\n {terminalLoading ? (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-center\">\n <Loader2 className=\"w-8 h-8 text-text-secondary animate-spin mx-auto mb-3\" />\n <p className=\"text-text-secondary text-sm\">\n {tr('sessionDetails.startingTerminal', 'Starting terminal for')} {session.name}\n ...\n </p>\n <p className=\"text-text-tertiary text-xs mt-1\">\n {tr(\n 'sessionDetails.settingUpTunnel',\n 'Setting up tmux + ttyd + cloudflared tunnel'\n )}\n </p>\n </div>\n </div>\n ) : terminalError ? (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-center max-w-md\">\n <AlertCircle className=\"w-8 h-8 text-status-error-text mx-auto mb-3\" />\n <p className=\"text-status-error-text text-sm font-medium\">\n {tr('sessionDetails.failedStartTerminal', 'Failed to start terminal')}\n </p>\n <p className=\"text-text-secondary text-xs mt-2\">{terminalError}</p>\n <button\n onClick={handleStartTerminal}\n className=\"mt-4 px-4 py-2 bg-bg-muted text-text-primary text-sm rounded-md hover:bg-bg-sunken transition-colors\"\n >\n {tr('sessionDetails.retry', 'Retry')}\n </button>\n </div>\n </div>\n ) : terminalUrl ? (\n <iframe\n src={terminalUrl}\n title={`Terminal - ${session.name}`}\n className=\"w-full h-full border-0\"\n allow=\"clipboard-read; clipboard-write\"\n />\n ) : (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-center\">\n <Terminal className=\"w-8 h-8 text-text-tertiary mx-auto mb-3\" />\n <p className=\"text-text-secondary text-sm\">\n {tr('sessionDetails.noTerminalRunning', 'No terminal running')}\n </p>\n <p className=\"text-text-tertiary text-xs mt-1\">\n {agent\n ? tr(\n 'sessionDetails.clickOpenTerminalHint',\n 'Click \"Open Terminal\" to create a tmux session with a browser terminal.'\n )\n : tr(\n 'sessionDetails.noAgentForSession',\n 'No agent is assigned to this session.'\n )}\n </p>\n {agent && (\n <button\n onClick={handleStartTerminal}\n disabled={terminalLoading}\n className=\"mt-4 px-4 py-2 bg-bg-muted text-text-primary text-sm rounded-md hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {terminalLoading\n ? tr('sessionDetails.opening', 'Opening...')\n : tr('sessionDetails.openTerminal', 'Open Terminal')}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Terminal collapsed indicator - show a clickable bar */}\n {!terminalOpen && (terminalUrl || terminalError) && (\n <div className=\"border-t border-border-default bg-bg-sunken shrink-0\">\n <button\n onClick={() => setTerminalOpen(true)}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-text-secondary hover:text-text-primary transition-colors text-xs font-medium uppercase tracking-wide w-full\"\n title={tr('sessionDetails.expandTerminal', 'Expand terminal')}\n >\n <Terminal className=\"w-3.5 h-3.5\" />\n {tr('sessionDetails.terminal', 'Terminal')} - {session.name}\n <ChevronUp className=\"w-3 h-3 ml-1\" />\n </button>\n </div>\n )}\n\n <ConfirmDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title={getQuotaDialogContent('session').title}\n message={getQuotaDialogContent('session').message}\n confirmLabel=\"View Billing\"\n cancelLabel=\"Dismiss\"\n variant=\"warning\"\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionDetailsPage.js","names":[],"sources":["../../src/pages/SessionDetailsPage.tsx"],"sourcesContent":["import { useState, useCallback, useEffect } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { EntityTagPicker } from '@/components/shared/EntityTagPicker';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useParams } from 'react-router-dom';\nimport { useVibeControlsStore } from '@/store/vibeControlsStore';\nimport {\n ArrowLeft,\n Terminal,\n Play,\n Square,\n RotateCcw,\n ExternalLink,\n Server,\n Zap,\n Clock,\n Folder,\n Code,\n Variable,\n Hash,\n RefreshCw,\n Loader2,\n AlertCircle,\n Maximize2,\n Minimize2,\n ChevronDown,\n ChevronUp,\n Pencil,\n Check,\n X,\n Tag,\n} from 'lucide-react';\nimport {\n PageHeader,\n Card,\n StatusBadge,\n EmptyState,\n ErrorState,\n ConfirmDialog,\n} from '@/components/shared';\nimport { MotionPage, MotionList, MotionItem } from '@burdenoff/fe-libs/shared/motion';\nimport { useVibeControls, useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport {\n useGetSessionQuery,\n useStartSessionMutation,\n useStopSessionMutation,\n useRestartSessionMutation,\n useStartSessionTerminalMutation,\n useRestartSessionTerminalMutation,\n useUpdateSessionMutation,\n} from '@/generated/wspace-operations';\nimport { getQuotaDialogContent, isQuotaExhaustedError } from '@/utils/quotaUtils';\n\n/**\n * Resolves the terminal URL for a session.\n * Each session gets its own ttyd instance + cloudflared tunnel.\n * The URL is set by the backend's startSessionTerminal mutation.\n */\nfunction getTerminalUrl(session: { ttydUrl?: string | null }): string | null {\n return session.ttydUrl || null;\n}\n\n/**\n * Session details page - shows comprehensive information about a single session\n * with an integrated terminal panel.\n */\nexport function SessionDetailsPage() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n const { id } = useParams<{ id: string }>();\n const { basePath: basePathProp } = useVibeControls();\n const basePath = basePathProp || '';\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n\n const [startSession] = useStartSessionMutation({ refetchQueries: ['GetSession'] });\n const [stopSession] = useStopSessionMutation({ refetchQueries: ['GetSession'] });\n const [restartSession] = useRestartSessionMutation({ refetchQueries: ['GetSession'] });\n const [startSessionTerminal] = useStartSessionTerminalMutation({\n refetchQueries: ['GetSession'],\n });\n const [restartSessionTerminal] = useRestartSessionTerminalMutation({\n refetchQueries: ['GetSession'],\n });\n const [updateSession] = useUpdateSessionMutation({ refetchQueries: ['GetSession'] });\n\n // Command/working-directory inline edit state\n const [editingCommand, setEditingCommand] = useState(false);\n const [editCommand, setEditCommand] = useState('');\n const [editWorkingDirectory, setEditWorkingDirectory] = useState('');\n const [editSaving, setEditSaving] = useState(false);\n\n const handleEditCommandOpen = () => {\n setEditCommand(session?.command || '');\n setEditWorkingDirectory(session?.workingDirectory || '');\n setEditingCommand(true);\n };\n\n const handleEditCommandSave = async () => {\n if (!session?.id) return;\n setEditSaving(true);\n try {\n await updateSession({\n variables: {\n id: session.id,\n input: {\n command: editCommand || null,\n workingDirectory: editWorkingDirectory || null,\n },\n },\n });\n setEditingCommand(false);\n } finally {\n setEditSaving(false);\n }\n };\n\n // Fetch session by ID from GraphQL API\n const { data, loading, error, refetch } = useGetSessionQuery({\n variables: { id: id || '' },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n // Get session from response\n const session = data?.session;\n\n // Get related agent and vibe from the session response\n const agent = session?.agent || null;\n const vibe = session?.vibe || null;\n\n // ── Sync active context ────────────────────────────────────────────────\n useEffect(() => {\n if (session) {\n useVibeControlsStore.setState({\n activeAgentId: (agent?.id as string) ?? null,\n selectedAgentId: (agent?.id as string) ?? null,\n activeVibeId: (vibe?.id as string) ?? null,\n selectedVibeId: (vibe?.id as string) ?? null,\n activeSessionId: session.id,\n selectedSessionId: session.id,\n });\n }\n }, [session?.id, agent?.id, vibe?.id]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Terminal state\n const [terminalOpen, setTerminalOpen] = useState(true);\n const [terminalMaximized, setTerminalMaximized] = useState(false);\n const [terminalLoading, setTerminalLoading] = useState(false);\n const [terminalError, setTerminalError] = useState<string | null>(null);\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n\n const terminalUrl = session ? getTerminalUrl(session) : null;\n\n const handleBack = () => {\n navigate('/sessions');\n };\n\n const handleStartSession = async () => {\n if (!session?.id) return;\n try {\n await startSession({ variables: { id: session.id } });\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n console.error('Failed to start session:', err);\n }\n };\n\n const handleStopSession = async () => {\n if (!session?.id) return;\n try {\n await stopSession({ variables: { id: session.id } });\n } catch (err) {\n console.error('Failed to stop session:', err);\n }\n };\n\n const handleRestartSession = async () => {\n if (!session?.id) return;\n try {\n await restartSession({ variables: { id: session.id } });\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n console.error('Failed to restart session:', err);\n }\n };\n\n const handleStartTerminal = useCallback(async () => {\n if (!session) return;\n setTerminalLoading(true);\n setTerminalError(null);\n try {\n // Call the backend mutation which orchestrates agent API calls server-side\n // (creates tmux session, starts ttyd, starts cloudflared tunnel, saves ttydUrl)\n const result = await startSessionTerminal({ variables: { id: session.id } });\n if (result.error && isQuotaExhaustedError(result.error)) {\n setShowQuotaExhausted(true);\n } else if (result.error) {\n setTerminalError(result.error.message);\n } else if (!result.data?.startSessionTerminal) {\n setTerminalError('Failed to start terminal');\n } else {\n setTerminalOpen(true);\n }\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n const message = err instanceof Error ? err.message : 'Failed to start terminal';\n setTerminalError(message);\n } finally {\n setTerminalLoading(false);\n }\n }, [session, startSessionTerminal]);\n\n const handleRestartTerminal = useCallback(async () => {\n if (!session) return;\n setTerminalLoading(true);\n setTerminalError(null);\n try {\n const result = await restartSessionTerminal({ variables: { id: session.id } });\n if (result.error && isQuotaExhaustedError(result.error)) {\n setShowQuotaExhausted(true);\n } else if (result.error) {\n setTerminalError(result.error.message);\n } else if (!result.data?.restartSessionTerminal) {\n setTerminalError('Failed to restart terminal');\n } else {\n setTerminalOpen(true);\n }\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n setShowQuotaExhausted(true);\n return;\n }\n\n const message = err instanceof Error ? err.message : 'Failed to restart terminal';\n setTerminalError(message);\n } finally {\n setTerminalLoading(false);\n }\n }, [session, restartSessionTerminal]);\n\n const handleOpenInNewTab = useCallback(() => {\n if (terminalUrl) {\n window.open(terminalUrl, '_blank');\n }\n }, [terminalUrl]);\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.loadingPermissions', 'Loading permissions...')}\n </p>\n </div>\n );\n if (!hasPermission(VIBE_PERMISSIONS.SESSION_READ))\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('sessionDetails.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'sessionDetails.accessDeniedDesc',\n \"You don't have permission to access this page.\"\n )}\n </p>\n </div>\n </div>\n );\n\n const handleAgentClick = () => {\n if (!agent) return;\n navigate(`/agents/${agent.id}`);\n };\n\n const handleVibeClick = () => {\n if (!vibe) return;\n navigate(`/vibes/${vibe.id}`);\n };\n\n const formatTimestamp = (timestamp: string | null | undefined) => {\n if (!timestamp) return 'Never';\n const diff = Date.now() - new Date(timestamp).getTime();\n if (diff < 60000) return 'Just now';\n if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;\n if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;\n return new Date(timestamp).toLocaleDateString();\n };\n\n // Guard states wrapped in MotionPage to prevent unmount/remount animation replay\n if (loading && !session) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n {tr('sessionDetails.backToSessions', 'Back to Sessions')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n if (error && !session) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n Back to Sessions\n </button>\n <ErrorState\n title={tr('sessionDetails.failedLoad', 'Failed to load session')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n if (!session) {\n return (\n <MotionPage className=\"space-y-6 p-4 sm:p-6 bg-bg-surface min-h-screen\">\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n Back to Sessions\n </button>\n <EmptyState\n icon={<Terminal className=\"w-8 h-8 text-text-secondary\" />}\n title={tr('sessionDetails.notFound', 'Session not found')}\n description={`${tr('sessionDetails.notFoundDescPrefix', 'No session with ID')} \"${id}\" ${tr('sessionDetails.notFoundDescSuffix', 'exists')}`}\n action={\n <button\n onClick={handleBack}\n className=\"px-4 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors\"\n >\n {tr('sessionDetails.backToSessions', 'Back to Sessions')}\n </button>\n }\n />\n </MotionPage>\n );\n }\n\n const isRunning = session.status === 'RUNNING';\n const terminalHeight = terminalMaximized ? 'h-[calc(100vh-200px)]' : 'h-[280px] sm:h-[420px]';\n\n return (\n <MotionPage className=\"flex flex-col bg-bg-surface min-h-screen\">\n {/* Main content - scrollable */}\n <div\n className={`flex-1 overflow-y-auto space-y-6 p-4 sm:p-6 ${terminalOpen && terminalUrl ? 'pb-2' : ''}`}\n >\n {/* Back Button */}\n <button\n onClick={handleBack}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"w-4 h-4\" />\n Back to Sessions\n </button>\n\n {/* Header */}\n <PageHeader\n title={session.name}\n description={session.command || 'No command specified'}\n breadcrumb={[\n { label: 'Sessions', path: basePath ? `${basePath}/sessions` : '/sessions' },\n { label: session.name },\n ]}\n actions={\n <div className=\"flex items-center gap-2 flex-wrap\">\n <button\n onClick={() => refetch()}\n disabled={loading}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title=\"Refresh\"\n >\n <RefreshCw className={`w-4 h-4 ${loading ? 'animate-spin' : ''}`} />\n </button>\n {isRunning ? (\n <>\n <button\n onClick={handleStopSession}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <Square className=\"w-4 h-4\" />\n {tr('sessionDetails.stopCommand', 'Stop Command')}\n </button>\n <button\n onClick={handleRestartSession}\n className=\"flex items-center gap-2 px-3 py-2 bg-bg-sunken text-text-primary rounded-md hover:bg-bg-sunken/80 transition-colors\"\n >\n <RotateCcw className=\"w-4 h-4\" />\n {tr('sessionDetails.restartCommand', 'Restart Command')}\n </button>\n </>\n ) : (\n <button\n onClick={handleStartSession}\n className=\"flex items-center gap-2 px-3 py-2 bg-status-success-bg text-status-success-text rounded-md hover:opacity-80 transition-colors\"\n >\n <Play className=\"w-4 h-4\" />\n {tr('sessionDetails.runCommand', 'Run Command')}\n </button>\n )}\n {/* Terminal toggle + open in new tab */}\n {terminalUrl ? (\n <>\n <button\n onClick={() => setTerminalOpen((prev) => !prev)}\n className={`flex items-center gap-2 px-3 py-2 rounded-md transition-colors ${\n terminalOpen\n ? 'bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover'\n : 'bg-bg-sunken text-text-primary hover:bg-bg-sunken/80'\n }`}\n title={\n terminalOpen\n ? tr('sessionDetails.hideTerminal', 'Hide terminal')\n : tr('sessionDetails.showTerminal', 'Show terminal')\n }\n >\n <Terminal className=\"w-4 h-4\" />\n {tr('sessionDetails.terminal', 'Terminal')}\n </button>\n <button\n onClick={handleRestartTerminal}\n disabled={terminalLoading}\n className=\"flex items-center px-2 py-2 bg-bg-sunken text-text-secondary rounded-md hover:text-text-primary hover:bg-bg-sunken/80 transition-colors disabled:opacity-50\"\n title={tr(\n 'sessionDetails.restartTerminalTitle',\n 'Restart terminal (new tunnel)'\n )}\n >\n {terminalLoading ? (\n <Loader2 className=\"w-3.5 h-3.5 animate-spin\" />\n ) : (\n <RotateCcw className=\"w-3.5 h-3.5\" />\n )}\n </button>\n <button\n onClick={handleOpenInNewTab}\n className=\"flex items-center px-2 py-2 bg-bg-sunken text-text-secondary rounded-md hover:text-text-primary hover:bg-bg-sunken/80 transition-colors\"\n title={tr('sessionDetails.openInNewTab', 'Open terminal in new tab')}\n >\n <ExternalLink className=\"w-4 h-4\" />\n </button>\n </>\n ) : (\n <button\n onClick={handleStartTerminal}\n disabled={terminalLoading || !agent}\n className=\"flex items-center gap-2 px-3 py-2 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n title={\n !agent\n ? tr('sessionDetails.noAgentAssigned', 'No agent assigned')\n : !agent.tunnelUrl\n ? tr(\n 'sessionDetails.agentNoTunnelUrl',\n 'Agent has no tunnel URL configured'\n )\n : tr('sessionDetails.openTerminal', 'Open terminal')\n }\n >\n {terminalLoading ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Terminal className=\"w-4 h-4\" />\n )}\n {tr('sessionDetails.openTerminal', 'Open Terminal')}\n </button>\n )}\n </div>\n }\n />\n\n {/* Status Cards */}\n <MotionList stagger={0.04} className=\"grid grid-cols-2 sm:grid-cols-4 gap-4\">\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Terminal className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.statusLabel', 'Status')}\n </p>\n <StatusBadge status={session.status} size=\"md\" />\n </div>\n </div>\n </Card>\n </MotionItem>\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Code className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.typeLabel', 'Type')}\n </p>\n <p className=\"font-semibold text-text-primary\">{session.type}</p>\n </div>\n </div>\n </Card>\n </MotionItem>\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Hash className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.pidLabel', 'PID')}\n </p>\n <p className=\"font-semibold text-text-primary\">{session.pid || 'N/A'}</p>\n </div>\n </div>\n </Card>\n </MotionItem>\n <MotionItem>\n <Card className=\"p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.agentLabel', 'Agent')}\n </p>\n <p className=\"font-semibold text-text-primary truncate\">\n {agent?.name || 'Unknown'}\n </p>\n </div>\n </div>\n </Card>\n </MotionItem>\n </MotionList>\n\n {/* Command */}\n <Card>\n <div className=\"p-4 border-b border-border-default flex items-center justify-between\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Code className=\"w-5 h-5\" />\n {tr('sessionDetails.commandTitle', 'Command')}\n </h3>\n {!editingCommand && (\n <button\n onClick={handleEditCommandOpen}\n className=\"p-1.5 rounded text-text-secondary hover:text-text-primary hover:bg-bg-sunken transition-colors\"\n title={tr('sessionDetails.editCommandTitle', 'Edit command and working directory')}\n >\n <Pencil className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n <div className=\"p-4\">\n {editingCommand ? (\n <div className=\"space-y-3\">\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n {tr('sessionDetails.commandLabel', 'Command')}\n </label>\n <input\n type=\"text\"\n value={editCommand}\n onChange={(e) => setEditCommand(e.target.value)}\n placeholder={tr('sessionDetails.commandPlaceholder', 'bun run dev')}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n autoFocus\n />\n </div>\n <div>\n <label className=\"block text-xs font-medium text-text-secondary mb-1\">\n {tr('sessionDetails.workingDirLabel', 'Working Directory')}\n </label>\n <input\n type=\"text\"\n value={editWorkingDirectory}\n onChange={(e) => setEditWorkingDirectory(e.target.value)}\n placeholder={tr('sessionDetails.workingDirPlaceholder', '/home/user/myproject')}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg font-mono\"\n />\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={handleEditCommandSave}\n disabled={editSaving}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {editSaving ? (\n <Loader2 className=\"w-3.5 h-3.5 animate-spin\" />\n ) : (\n <Check className=\"w-3.5 h-3.5\" />\n )}\n {tr('sessionDetails.save', 'Save')}\n </button>\n <button\n onClick={() => setEditingCommand(false)}\n disabled={editSaving}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-sm bg-bg-sunken text-text-primary rounded-md hover:bg-bg-elevated transition-colors disabled:opacity-50\"\n >\n <X className=\"w-3.5 h-3.5\" />\n {tr('sessionDetails.cancel', 'Cancel')}\n </button>\n </div>\n </div>\n ) : (\n <>\n <div className=\"bg-bg-sunken rounded-md p-3 font-mono text-sm text-text-primary overflow-x-auto\">\n ${' '}\n {session.command ||\n tr('sessionDetails.noCommandSpecified', 'No command specified')}\n </div>\n <div className=\"mt-3 flex items-center gap-2 text-sm text-text-secondary\">\n <Folder className=\"w-4 h-4\" />\n {tr('sessionDetails.workingDirectory', 'Working Directory')}:{' '}\n <span className=\"text-text-primary font-mono\">\n {session.workingDirectory || (\n <em className=\"not-italic text-text-placeholder\">\n {tr('sessionDetails.workingDirDefault', 'not set — defaults to OS home')}\n </em>\n )}\n </span>\n </div>\n </>\n )}\n </div>\n </Card>\n\n {/* Environment Variables */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Variable className=\"w-5 h-5\" />\n {tr('sessionDetails.envVars', 'Environment Variables')}\n </h3>\n </div>\n <div className=\"p-4\">\n {session.environmentVariables &&\n Object.keys(session.environmentVariables).length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {Object.entries(session.environmentVariables).map(([key, value]) => (\n <span\n key={key}\n className=\"px-3 py-1 bg-bg-sunken text-text-primary text-sm rounded-full font-mono\"\n >\n {key}={String(value)}\n </span>\n ))}\n </div>\n ) : (\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.noEnvVars', 'No environment variables configured')}\n </p>\n )}\n </div>\n </Card>\n\n {/* Last Output */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Terminal className=\"w-5 h-5\" />\n {tr('sessionDetails.lastOutput', 'Last Output')}\n </h3>\n </div>\n <div className=\"p-4\">\n {session.lastOutput ? (\n <div className=\"bg-bg-sunken rounded-md p-3 font-mono text-sm text-text-primary overflow-x-auto whitespace-pre-wrap\">\n {session.lastOutput}\n </div>\n ) : (\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.noOutput', 'No output captured')}\n </p>\n )}\n </div>\n </Card>\n\n {/* Related Vibe */}\n {vibe && (\n <Card onClick={handleVibeClick} hoverable>\n <div className=\"p-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Zap className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.relatedVibe', 'Related Vibe')}\n </p>\n <p className=\"font-medium text-text-primary\">{vibe.name}</p>\n {vibe.path && (\n <p className=\"text-sm text-text-secondary truncate max-w-md\">{vibe.path}</p>\n )}\n </div>\n </div>\n <StatusBadge status={vibe.status} />\n </div>\n </Card>\n )}\n\n {/* Related Agent */}\n {agent && (\n <Card onClick={handleAgentClick} hoverable>\n <div className=\"p-4 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-bg-sunken flex items-center justify-center\">\n <Server className=\"w-5 h-5 text-text-secondary\" />\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.runningOnAgent', 'Running on Agent')}\n </p>\n <p className=\"font-medium text-text-primary\">{agent.name}</p>\n <p className=\"text-sm text-text-secondary\">{agent.hostname}</p>\n </div>\n </div>\n <StatusBadge status={agent.isActive ? 'ACTIVE' : 'OFFLINE'} />\n </div>\n </Card>\n )}\n\n {/* Metadata */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Clock className=\"w-5 h-5\" />\n {tr('sessionDetails.timeline', 'Timeline')}\n </h3>\n </div>\n <div className=\"p-4\">\n <div className=\"grid grid-cols-1 sm:grid-cols-3 gap-4 text-sm\">\n <div>\n <p className=\"text-text-secondary\">\n {tr('sessionDetails.autoStart', 'Auto Start')}\n </p>\n <p className=\"font-medium text-text-primary\">\n {session.autoStart\n ? tr('sessionDetails.yes', 'Yes')\n : tr('sessionDetails.no', 'No')}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('sessionDetails.created', 'Created')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(session.createdAt)}\n </p>\n </div>\n <div>\n <p className=\"text-text-secondary\">{tr('sessionDetails.updated', 'Updated')}</p>\n <p className=\"font-medium text-text-primary\">\n {formatTimestamp(session.updatedAt)}\n </p>\n </div>\n </div>\n {session.exitCode !== null && session.exitCode !== undefined && (\n <div className=\"mt-4 pt-4 border-t border-border-default\">\n <p className=\"text-sm text-text-secondary\">\n {tr('sessionDetails.exitCode', 'Exit Code')}\n </p>\n <p\n className={`font-medium ${session.exitCode === 0 ? 'text-status-success-text' : 'text-status-error-text'}`}\n >\n {session.exitCode}\n </p>\n </div>\n )}\n </div>\n </Card>\n\n {/* Tags */}\n <Card>\n <div className=\"p-4 border-b border-border-default\">\n <h3 className=\"font-semibold text-text-primary flex items-center gap-2\">\n <Tag className=\"w-5 h-5\" />\n {tr('sessionDetails.tags', 'Tags')}\n </h3>\n </div>\n <div className=\"p-4\">\n <EntityTagPicker entityType=\"VIBECONTROLS_SESSION\" entityId={session.id} />\n </div>\n </Card>\n </div>\n\n {/* Integrated Terminal Panel - docked at bottom */}\n {terminalOpen && (\n <div className=\"border-t border-border-default bg-bg-surface shrink-0\">\n {/* Terminal header bar */}\n <div className=\"flex items-center bg-bg-sunken border-b border-border-default\">\n <button\n onClick={() => setTerminalOpen(false)}\n className=\"flex items-center gap-1.5 px-3 py-2 text-text-secondary hover:text-text-primary transition-colors text-xs font-medium uppercase tracking-wide\"\n title={tr('sessionDetails.collapseTerminal', 'Collapse terminal')}\n >\n <Terminal className=\"w-3.5 h-3.5\" />\n {tr('sessionDetails.terminal', 'Terminal')}\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n <div className=\"flex items-center px-3 py-1.5 text-xs bg-bg-surface text-text-primary border-r border-border-subtle border-b-2 border-b-action-primary-bg\">\n <Terminal className=\"w-3 h-3 mr-1.5\" />\n {session.name}\n </div>\n <div className=\"flex-1\" />\n <div className=\"flex items-center gap-1 px-2\">\n {terminalUrl && (\n <button\n onClick={handleOpenInNewTab}\n className=\"p-1 text-text-secondary hover:text-text-primary transition-colors\"\n title={tr('sessionDetails.openInNewTabShort', 'Open in new tab')}\n >\n <ExternalLink className=\"w-3.5 h-3.5\" />\n </button>\n )}\n <button\n onClick={() => setTerminalMaximized((prev) => !prev)}\n className=\"p-1 text-text-secondary hover:text-text-primary transition-colors\"\n title={\n terminalMaximized\n ? tr('sessionDetails.restoreSize', 'Restore size')\n : tr('sessionDetails.maximize', 'Maximize')\n }\n >\n {terminalMaximized ? (\n <Minimize2 className=\"w-3.5 h-3.5\" />\n ) : (\n <Maximize2 className=\"w-3.5 h-3.5\" />\n )}\n </button>\n </div>\n </div>\n\n {/* Terminal content */}\n <div className={`${terminalHeight} bg-bg-inverse text-text-inverse`}>\n {terminalLoading ? (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-center\">\n <Loader2 className=\"w-8 h-8 text-text-secondary animate-spin mx-auto mb-3\" />\n <p className=\"text-text-secondary text-sm\">\n {tr('sessionDetails.startingTerminal', 'Starting terminal for')} {session.name}\n ...\n </p>\n <p className=\"text-text-tertiary text-xs mt-1\">\n {tr(\n 'sessionDetails.settingUpTunnel',\n 'Setting up tmux + ttyd + cloudflared tunnel'\n )}\n </p>\n </div>\n </div>\n ) : terminalError ? (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-center max-w-md\">\n <AlertCircle className=\"w-8 h-8 text-status-error-text mx-auto mb-3\" />\n <p className=\"text-status-error-text text-sm font-medium\">\n {tr('sessionDetails.failedStartTerminal', 'Failed to start terminal')}\n </p>\n <p className=\"text-text-secondary text-xs mt-2\">{terminalError}</p>\n <button\n onClick={handleStartTerminal}\n className=\"mt-4 px-4 py-2 bg-bg-muted text-text-primary text-sm rounded-md hover:bg-bg-sunken transition-colors\"\n >\n {tr('sessionDetails.retry', 'Retry')}\n </button>\n </div>\n </div>\n ) : terminalUrl ? (\n <iframe\n src={terminalUrl}\n title={`Terminal - ${session.name}`}\n className=\"w-full h-full border-0\"\n allow=\"clipboard-read; clipboard-write\"\n />\n ) : (\n <div className=\"flex items-center justify-center h-full\">\n <div className=\"text-center\">\n <Terminal className=\"w-8 h-8 text-text-tertiary mx-auto mb-3\" />\n <p className=\"text-text-secondary text-sm\">\n {tr('sessionDetails.noTerminalRunning', 'No terminal running')}\n </p>\n <p className=\"text-text-tertiary text-xs mt-1\">\n {agent\n ? tr(\n 'sessionDetails.clickOpenTerminalHint',\n 'Click \"Open Terminal\" to create a tmux session with a browser terminal.'\n )\n : tr(\n 'sessionDetails.noAgentForSession',\n 'No agent is assigned to this session.'\n )}\n </p>\n {agent && (\n <button\n onClick={handleStartTerminal}\n disabled={terminalLoading}\n className=\"mt-4 px-4 py-2 bg-bg-muted text-text-primary text-sm rounded-md hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {terminalLoading\n ? tr('sessionDetails.opening', 'Opening...')\n : tr('sessionDetails.openTerminal', 'Open Terminal')}\n </button>\n )}\n </div>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Terminal collapsed indicator - show a clickable bar */}\n {!terminalOpen && (terminalUrl || terminalError) && (\n <div className=\"border-t border-border-default bg-bg-sunken shrink-0\">\n <button\n onClick={() => setTerminalOpen(true)}\n className=\"flex items-center gap-1.5 px-3 py-1.5 text-text-secondary hover:text-text-primary transition-colors text-xs font-medium uppercase tracking-wide w-full\"\n title={tr('sessionDetails.expandTerminal', 'Expand terminal')}\n >\n <Terminal className=\"w-3.5 h-3.5\" />\n {tr('sessionDetails.terminal', 'Terminal')} - {session.name}\n <ChevronUp className=\"w-3 h-3 ml-1\" />\n </button>\n </div>\n )}\n\n <ConfirmDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title={getQuotaDialogContent('session').title}\n message={getQuotaDialogContent('session').message}\n confirmLabel=\"View Billing\"\n cancelLabel=\"Dismiss\"\n variant=\"warning\"\n />\n </MotionPage>\n );\n}\n"],"mappings":"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"}
|