From b3a57443217a5356d8849953926ebb5a1075fcb5 Mon Sep 17 00:00:00 2001 From: Cristian Pufu Date: Fri, 13 Feb 2026 07:10:44 +0200 Subject: [PATCH 1/5] feat: redesign new run page with setup view and mode cards Replace Run/Chat buttons with Autonomous/Conversational mode cards. Both modes navigate to a new setup view with graph + side panel where users can set breakpoints before starting execution. - Autonomous: JSON input textarea + Execute button in side panel - Conversational: chat message input + Send button in side panel - New RunEventsPanel sidebar for autonomous runs showing state events - Add stateEvents accumulation to store and WebSocket handler - Add #/setup/:entrypoint/:mode hash route Co-Authored-By: Claude Opus 4.6 --- src/uipath/dev/server/frontend/src/App.tsx | 12 +- .../src/components/runs/NewRunPanel.tsx | 359 ++++++------------ .../src/components/runs/RunDetailsPanel.tsx | 48 +++ .../src/components/runs/RunEventsPanel.tsx | 69 ++++ .../src/components/runs/SetupView.tsx | 350 +++++++++++++++++ .../server/frontend/src/hooks/useHashRoute.ts | 22 +- .../server/frontend/src/store/useRunStore.ts | 15 + .../server/frontend/src/store/useWebSocket.ts | 5 +- .../dev/server/frontend/tsconfig.tsbuildinfo | 2 +- .../server/static/assets/index-4PiRVHPO.css | 1 + .../server/static/assets/index-CSzbT0ru.css | 1 - .../server/static/assets/index-D1KugSSh.js | 145 +++++++ .../server/static/assets/index-aLZt7pYt.js | 145 ------- src/uipath/dev/server/static/index.html | 4 +- 14 files changed, 770 insertions(+), 408 deletions(-) create mode 100644 src/uipath/dev/server/frontend/src/components/runs/RunEventsPanel.tsx create mode 100644 src/uipath/dev/server/frontend/src/components/runs/SetupView.tsx create mode 100644 src/uipath/dev/server/static/assets/index-4PiRVHPO.css delete mode 100644 src/uipath/dev/server/static/assets/index-CSzbT0ru.css create mode 100644 src/uipath/dev/server/static/assets/index-D1KugSSh.js delete mode 100644 src/uipath/dev/server/static/assets/index-aLZt7pYt.js diff --git a/src/uipath/dev/server/frontend/src/App.tsx b/src/uipath/dev/server/frontend/src/App.tsx index 069e78d..f58805f 100644 --- a/src/uipath/dev/server/frontend/src/App.tsx +++ b/src/uipath/dev/server/frontend/src/App.tsx @@ -5,6 +5,7 @@ import { listRuns, listEntrypoints, getRun } from "./api/client"; import { useHashRoute } from "./hooks/useHashRoute"; import Sidebar from "./components/layout/Sidebar"; import NewRunPanel from "./components/runs/NewRunPanel"; +import SetupView from "./components/runs/SetupView"; import RunDetailsPanel from "./components/runs/RunDetailsPanel"; export default function App() { @@ -20,7 +21,7 @@ export default function App() { setChatMessages, setEntrypoints, } = useRunStore(); - const { view, runId: routeRunId, tab, navigate } = useHashRoute(); + const { view, runId: routeRunId, tab, setupEntrypoint, setupMode, navigate } = useHashRoute(); // Sync route runId → store selection useEffect(() => { @@ -126,7 +127,14 @@ export default function App() { />
{view === "new" ? ( - + + ) : view === "setup" && setupEntrypoint && setupMode ? ( + ) : selectedRun ? ( ) : ( diff --git a/src/uipath/dev/server/frontend/src/components/runs/NewRunPanel.tsx b/src/uipath/dev/server/frontend/src/components/runs/NewRunPanel.tsx index cb4f614..7ddc58f 100644 --- a/src/uipath/dev/server/frontend/src/components/runs/NewRunPanel.tsx +++ b/src/uipath/dev/server/frontend/src/components/runs/NewRunPanel.tsx @@ -1,111 +1,29 @@ -import { useEffect, useState, useCallback } from "react"; +import { useEffect, useState } from "react"; import { useRunStore } from "../../store/useRunStore"; -import { getEntrypointMockInput, createRun } from "../../api/client"; +import { useHashRoute } from "../../hooks/useHashRoute"; -interface Props { - onRunCreated: (runId: string) => void; -} - -interface SchemaError { - message: string; - type?: string; - error?: string; - traceback?: string; -} - -export default function NewRunPanel({ onRunCreated }: Props) { +export default function NewRunPanel() { + const { navigate } = useHashRoute(); const entrypoints = useRunStore((s) => s.entrypoints); const [selectedEp, setSelectedEp] = useState(""); - const [inputJson, setInputJson] = useState("{}"); - const [loading, setLoading] = useState(null); - const [loadingSchema, setLoadingSchema] = useState(false); - const [schemaError, setSchemaError] = useState(null); - // Cache mock inputs so we don't re-fetch on every switch - const [mockCache, setMockCache] = useState>({}); - - // Select first entrypoint when available and none selected useEffect(() => { if (!selectedEp && entrypoints.length > 0) { setSelectedEp(entrypoints[0]); } }, [entrypoints, selectedEp]); - // Fetch mock input when entrypoint changes - const loadMockInput = useCallback( - async (ep: string) => { - if (!ep) return; - - // Use cache if available - if (mockCache[ep]) { - setInputJson(mockCache[ep]); - setSchemaError(null); - return; - } - - setLoadingSchema(true); - setSchemaError(null); - try { - const result = await getEntrypointMockInput(ep); - const json = JSON.stringify(result.mock_input, null, 2); - setInputJson(json); - setMockCache((prev) => ({ ...prev, [ep]: json })); - } catch (err: any) { - console.error("Failed to load mock input:", err); - // Parse error details from the HTTP exception - const errorDetail = err.detail || {}; - setSchemaError({ - message: errorDetail.message || `Failed to load schema for "${ep}"`, - type: errorDetail.type, - error: errorDetail.error, - traceback: errorDetail.traceback, - }); - setInputJson("{}"); - } finally { - setLoadingSchema(false); - } - }, - [mockCache], - ); - - useEffect(() => { - if (selectedEp) { - loadMockInput(selectedEp); - } - }, [selectedEp, loadMockInput]); - - const handleSubmit = async (mode: "run" | "debug" | "chat") => { + const handleModeSelect = (mode: "run" | "chat") => { if (!selectedEp) return; - - let parsed: Record; - try { - parsed = JSON.parse(inputJson); - } catch { - alert("Invalid JSON input"); - return; - } - - setLoading(mode); - try { - const run = await createRun(selectedEp, parsed, mode, []); - // Immediately add the run to the store so it's available when switching views - useRunStore.getState().upsertRun(run); - onRunCreated(run.id); - } catch (err) { - console.error("Failed to create run:", err); - } finally { - setLoading(null); - } + navigate(`#/setup/${encodeURIComponent(selectedEp)}/${mode}`); }; - const isDisabled = !!loading || !selectedEp || loadingSchema; - return (
-
+
{/* Header */} -
-
+
+

- Select an entrypoint and configure input + Select an entrypoint and choose a mode

{/* Entrypoint */} -
+
- {schemaError ? ( - - ) : ( - <> - {/* JSON Input */} -
-
- - {loadingSchema && ( - - Loading schema... - - )} -
-