From 82cb7bf375ed5e8eb07774848f73d4fb7cf2a27c Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Mon, 8 Jun 2026 16:43:07 +0200 Subject: [PATCH] whitelabel default timeout + test-job callbacks (#9469) Add a configurable `defaultTimeout` to the script/flow editor whitelabel customUi (replaces the hardcoded 300s default) and an `onTestJob` callback on ScriptBuilder/FlowBuilder that fires with the preview job id when a test run starts. Co-authored-by: Claude Opus 4.8 (1M context) --- frontend/src/lib/components/FlowBuilder.svelte | 8 ++++++-- frontend/src/lib/components/FlowPreviewContent.svelte | 4 ++-- frontend/src/lib/components/ScriptBuilder.svelte | 4 +++- frontend/src/lib/components/ScriptEditor.svelte | 11 ++++++++--- frontend/src/lib/components/custom_ui.ts | 6 ++++++ frontend/src/lib/components/flow_builder.ts | 3 +++ .../components/flows/content/FlowModuleTimeout.svelte | 5 ++++- .../components/flows/header/FlowPreviewButtons.svelte | 2 +- frontend/src/lib/components/script_builder.ts | 3 +++ 9 files changed, 36 insertions(+), 10 deletions(-) diff --git a/frontend/src/lib/components/FlowBuilder.svelte b/frontend/src/lib/components/FlowBuilder.svelte index 24459967ab..24c0071a5e 100644 --- a/frontend/src/lib/components/FlowBuilder.svelte +++ b/frontend/src/lib/components/FlowBuilder.svelte @@ -133,7 +133,8 @@ onSaveDraftError, onSaveDraftOnlyAtNewPath, onHistoryRestore, - onNavigate + onNavigate, + onTestJob }: FlowBuilderProps = $props() let initialPathStore = writable(initialPath) @@ -1267,11 +1268,14 @@ bind:localModuleStates bind:this={flowPreviewButtons} {loading} - onRunPreview={() => { + onRunPreview={(jobId) => { stepsInputArgs.resetManuallyEditedArgs() modulesTestStates.hideJobsInGraph() localModuleStates = {} showJobStatus = true + if (jobId) { + onTestJob?.({ jobId }) + } }} /> {/snippet} diff --git a/frontend/src/lib/components/FlowPreviewContent.svelte b/frontend/src/lib/components/FlowPreviewContent.svelte index 49f195cd0d..eb9bbea4e7 100644 --- a/frontend/src/lib/components/FlowPreviewContent.svelte +++ b/frontend/src/lib/components/FlowPreviewContent.svelte @@ -59,7 +59,7 @@ scrollTop?: number localModuleStates?: Record localDurationStatuses?: Record - onRunPreview?: () => void + onRunPreview?: (jobId?: string) => void render?: boolean onJobDone?: () => void upToId?: string | undefined @@ -200,7 +200,7 @@ savedArgs = $state.snapshot(previewArgs.val) inputSelected = undefined } - onRunPreview?.() + onRunPreview?.(newJobId) } catch (e) { sendUserToast('Could not run preview', true, undefined, e.toString()) isRunning = false diff --git a/frontend/src/lib/components/ScriptBuilder.svelte b/frontend/src/lib/components/ScriptBuilder.svelte index 325f2753e5..f5f59cec34 100644 --- a/frontend/src/lib/components/ScriptBuilder.svelte +++ b/frontend/src/lib/components/ScriptBuilder.svelte @@ -134,6 +134,7 @@ onSaveDraftError, onSaveDraft, onNavigate, + onTestJob, disableAi, initialTestPanelCollapsed = false, initialPathChosen = false @@ -1565,7 +1566,7 @@ if (script.timeout && script.timeout != undefined) { script.timeout = undefined } else { - script.timeout = 300 + script.timeout = customUi?.defaultTimeout ?? 300 } }} options={{ @@ -2084,6 +2085,7 @@ {disableAi} bind:selectedTab={selectedInputTab} {customUi} + {onTestJob} collabMode edit={initialPath != ''} on:format={() => { diff --git a/frontend/src/lib/components/ScriptEditor.svelte b/frontend/src/lib/components/ScriptEditor.svelte index a281b266da..c54924caf8 100644 --- a/frontend/src/lib/components/ScriptEditor.svelte +++ b/frontend/src/lib/components/ScriptEditor.svelte @@ -160,6 +160,9 @@ modules?: { [key: string]: ScriptModule } | null editorBarRight?: import('svelte').Snippet enablePreprocessorSnippet?: boolean + // Fired whenever a test run is started from this editor, with the + // preview job id. Used by whitelabel embedders to track test jobs. + onTestJob?: (e: { jobId: string }) => void // When true the right-hand test/run pane mounts collapsed. The user // can still expand it via `toggleTestPanel`. Defaults to false so the // regular /scripts/edit route keeps its current open-by-default UX; @@ -199,6 +202,7 @@ modules = $bindable(undefined), editorBarRight, enablePreprocessorSnippet = false, + onTestJob, initialTestPanelCollapsed = false }: Props = $props() @@ -729,6 +733,9 @@ undefined, activeModuleTab !== null ? undefined : modules ) + if (job) { + onTestJob?.({ jobId: job }) + } logPanel?.setFocusToLogs() return job } @@ -1357,9 +1364,7 @@ // width (Svelte wires a ResizeObserver for bind:clientWidth). let splitContainerWidth = $state(0) const TEST_PANE_MIN_PX = 400 - const testPaneMinPercent = $derived( - paneMinPercent(splitContainerWidth, TEST_PANE_MIN_PX) - ) + const testPaneMinPercent = $derived(paneMinPercent(splitContainerWidth, TEST_PANE_MIN_PX)) // Raw user-controlled test size (what the splitter wrote, or what the // toggle set). The size we actually pass to is clamped to the diff --git a/frontend/src/lib/components/custom_ui.ts b/frontend/src/lib/components/custom_ui.ts index 5f017ee950..64c6221aea 100644 --- a/frontend/src/lib/components/custom_ui.ts +++ b/frontend/src/lib/components/custom_ui.ts @@ -44,6 +44,9 @@ export type FlowBuilderWhitelabelCustomUi = { aiSandbox?: boolean suggestIntegration?: boolean suggestScript?: boolean + // Default timeout (in seconds) prefilled when enabling a custom step timeout. + // Defaults to 300 (5 minutes) when unset. + defaultTimeout?: number } export type DisplayResultUi = { @@ -130,4 +133,7 @@ export type ScriptBuilderWhitelabelCustomUi = { editorBar?: EditorBarUi previewPanel?: PreviewPanelUi tagSelectPlaceholder?: string + // Default timeout (in seconds) prefilled when enabling a custom script timeout. + // Defaults to 300 (5 minutes) when unset. + defaultTimeout?: number } diff --git a/frontend/src/lib/components/flow_builder.ts b/frontend/src/lib/components/flow_builder.ts index e91a06e430..5d2493b930 100644 --- a/frontend/src/lib/components/flow_builder.ts +++ b/frontend/src/lib/components/flow_builder.ts @@ -51,4 +51,7 @@ export type FlowBuilderProps = { onDetails?: ({ path }: { path: string }) => void onHistoryRestore?: () => void onNavigate?: (item: WorkspaceItem) => void + // Fired whenever a test run is started from the flow editor, with the + // preview job id. Used by whitelabel embedders to track test jobs. + onTestJob?: (e: { jobId: string }) => void } diff --git a/frontend/src/lib/components/flows/content/FlowModuleTimeout.svelte b/frontend/src/lib/components/flows/content/FlowModuleTimeout.svelte index 9987d748cd..39aaaa66f2 100644 --- a/frontend/src/lib/components/flows/content/FlowModuleTimeout.svelte +++ b/frontend/src/lib/components/flows/content/FlowModuleTimeout.svelte @@ -13,6 +13,7 @@ import PropPickerWrapper from '$lib/components/flows/propPicker/PropPickerWrapper.svelte' import type { FlowEditorContext } from '../types' import { getStepPropPicker } from '../previousResults' + import type { FlowBuilderWhitelabelCustomUi } from '$lib/components/custom_ui' interface Props { flowModule: FlowModule @@ -24,6 +25,8 @@ const { flowStore, flowStateStore, previewArgs } = getContext('FlowEditorContext') + const customUi = getContext('customUi') + let schema = $state(emptySchema()) schema.properties['timeout'] = { type: 'number' @@ -69,7 +72,7 @@ } else { flowModule.timeout = { type: 'static', - value: 300 + value: customUi?.defaultTimeout ?? 300 } } }} diff --git a/frontend/src/lib/components/flows/header/FlowPreviewButtons.svelte b/frontend/src/lib/components/flows/header/FlowPreviewButtons.svelte index 206c9f199b..2f1c016385 100644 --- a/frontend/src/lib/components/flows/header/FlowPreviewButtons.svelte +++ b/frontend/src/lib/components/flows/header/FlowPreviewButtons.svelte @@ -14,7 +14,7 @@ interface Props { loading?: boolean - onRunPreview?: () => void + onRunPreview?: (jobId?: string) => void onJobDone?: () => void localModuleStates?: Record suspendStatus: StateStore> diff --git a/frontend/src/lib/components/script_builder.ts b/frontend/src/lib/components/script_builder.ts index e561600181..cac47d4eef 100644 --- a/frontend/src/lib/components/script_builder.ts +++ b/frontend/src/lib/components/script_builder.ts @@ -48,6 +48,9 @@ export interface ScriptBuilderProps { onSeeDetails?: (e: { path: string }) => void onSaveDraftError?: (e: { path: string; error: any }) => void onNavigate?: (item: WorkspaceItem) => void + // Fired whenever a test run is started from the script editor, with the + // preview job id. Used by whitelabel embedders to track test jobs. + onTestJob?: (e: { jobId: string }) => void // Forwarded to the underlying ScriptEditor. When true, the right-hand // test/run pane opens collapsed. Used by the session preview. initialTestPanelCollapsed?: boolean