From 3417a2f7fbf5241c8256e76aa1aad08992e69db7 Mon Sep 17 00:00:00 2001 From: ciregenz Date: Mon, 11 May 2026 13:56:08 -0700 Subject: [PATCH] [eric] runtime: fix missing asyncio import in main.py + right-click Hard Reload on the App Builder reload button --- frontend/src/app/pages/Views/ViewEditor.tsx | 52 ++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/pages/Views/ViewEditor.tsx b/frontend/src/app/pages/Views/ViewEditor.tsx index 423034aa..4f614b39 100644 --- a/frontend/src/app/pages/Views/ViewEditor.tsx +++ b/frontend/src/app/pages/Views/ViewEditor.tsx @@ -7,6 +7,11 @@ import TextField from '@mui/material/TextField'; import Tabs from '@mui/material/Tabs'; import Tab from '@mui/material/Tab'; import Tooltip from '@mui/material/Tooltip'; +import Menu from '@mui/material/Menu'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import RestartAltIcon from '@mui/icons-material/RestartAlt'; import HtmlIcon from '@mui/icons-material/Code'; import PythonIcon from '@mui/icons-material/Terminal'; import SchemaIcon from '@mui/icons-material/DataObject'; @@ -633,6 +638,28 @@ const ViewEditor: React.FC = ({ output }) => { appendTerminalLine('frontend', level, text); }, [appendTerminalLine]); + // Reload button context menu — left-click is a soft reload (reloads + // the webview only); right-click opens this menu, which adds a Hard + // Reload that also restarts the persistent backend subprocess. + // Useful when backend.py has a Python-level error you can only clear + // by stopping and re-spawning the process. + const [reloadMenuAnchor, setReloadMenuAnchor] = useState(null); + const handleHardReload = useCallback(async () => { + setReloadMenuAnchor(null); + if (workspaceId) { + try { + const tok = getAuthToken(); + const headers: Record = { 'Content-Type': 'application/json' }; + if (tok) headers.Authorization = `Bearer ${tok}`; + await fetch(`${API_BASE}/outputs/workspace/${workspaceId}/runtime/restart`, { + method: 'POST', + headers, + }); + } catch { /* failures surface via the runtime log WS */ } + } + previewRef.current?.reload(); + }, [workspaceId]); + // Persistent backend lifecycle. Once we know the workspaceId: // 1. POST /runtime/start so the workspace's backend.py (if present) // gets spawned and an `OUTPUT_BACKEND_URL` lands in the preview's @@ -929,16 +956,39 @@ const ViewEditor: React.FC = ({ output }) => { {activeTab === TAB_PREVIEW && ( - + previewRef.current?.reload()} + onContextMenu={(e) => { + e.preventDefault(); + setReloadMenuAnchor(e.currentTarget as HTMLElement); + }} sx={{ mr: 1, color: c.text.muted }} > )} + setReloadMenuAnchor(null)} + anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} + transformOrigin={{ vertical: 'top', horizontal: 'right' }} + > + + + + + + + {/* Tab content */}