diff --git a/frontend/src/lib/components/ScriptEditor.svelte b/frontend/src/lib/components/ScriptEditor.svelte index facc6e9bb0..88436327d4 100644 --- a/frontend/src/lib/components/ScriptEditor.svelte +++ b/frontend/src/lib/components/ScriptEditor.svelte @@ -1250,8 +1250,37 @@ } aiChatManager.saveAndClear() aiChatManager.changeMode(AIMode.SCRIPT) + if (customUi?.previewPanel?.loadLastRunOnMount) { + void loadLastRunIntoTestPanel() + } }) + // Pull the most recent top-level completed job for this script path and + // feed it through the JobLoader so the preview pane renders its logs + + // result. Best-effort: any error (no job yet, network blip) leaves the + // panel empty rather than surfacing a toast — this is a passive "show + // what's there" affordance, not a user action. Skipped when a test is + // already running so a live job's stream is never clobbered. + async function loadLastRunIntoTestPanel(): Promise { + if (!path || !$workspaceStore) return + if (testIsLoading || testJob !== undefined) return + try { + const jobs = await JobService.listCompletedJobs({ + workspace: $workspaceStore, + scriptPathExact: path, + hasNullParent: true, + perPage: 1, + orderDesc: true + }) + const lastId = jobs[0]?.id + if (lastId && !testIsLoading && testJob === undefined) { + await jobLoader?.watchJob(lastId) + } + } catch (e) { + // Silent: empty preview pane is the natural fallback. + } + } + setLicense() export async function setCollaborationMode() { await setLicense() diff --git a/frontend/src/lib/components/assets/AssetGraph/AssetGraphDetailsPane.svelte b/frontend/src/lib/components/assets/AssetGraph/AssetGraphDetailsPane.svelte index 835aa6c5f5..8fe9825eed 100644 --- a/frontend/src/lib/components/assets/AssetGraph/AssetGraphDetailsPane.svelte +++ b/frontend/src/lib/components/assets/AssetGraph/AssetGraphDetailsPane.svelte @@ -812,7 +812,12 @@ hideArgs: true, argsAboveLogs: true, logsResultSideBySide: true, - downstreamSubscribers + downstreamSubscribers, + // Selecting a script node should immediately show + // "what happened last time it ran" — pulling the + // latest top-level completed job into the preview + // pane is far more useful than an empty placeholder. + loadLastRunOnMount: true } }} bind:code={script.content} diff --git a/frontend/src/lib/components/custom_ui.ts b/frontend/src/lib/components/custom_ui.ts index 05c55da9bf..4fe6833406 100644 --- a/frontend/src/lib/components/custom_ui.ts +++ b/frontend/src/lib/components/custom_ui.ts @@ -84,6 +84,13 @@ export type PreviewPanelUi = { // partitioned pipeline script that needs a `partition` arg to run). // No-op when the script has no input properties. argsAboveLogs?: boolean + // On mount, query the most recent top-level completed job for this + // script's path and load it into the preview pane so users immediately + // see the last run's logs/result instead of an empty panel. Used by the + // asset-graph details pane where selecting a script node should expose + // "what happened the last time this ran". No-op when a test is already + // in progress (we don't clobber a live run). + loadLastRunOnMount?: boolean } export type EditorBarUi = {