{#if render} {#if level === 0 && toggleExpandAll}
{#snippet text()} Keyboard navigation available - ↑/↓/Enter {/snippet}
Show timeline
Show inputs/results
{allExpanded ? 'Collapse All' : 'Expand All'} {#if allExpanded}
{:else}
{/if}
{/if}
0} isRunning={rootJob?.type === 'QueuedJob'} {isCurrent} {isExpanded} {toggleExpanded} class={rootJob?.type === undefined ? 'opacity-50' : ''} {select} > {#snippet label()}
{@render flowIcon(getFlowStatus(rootJob), flowInfo?.hasErrors)}
{mode === 'aiagent' ? 'AI Agent' : level == 0 ? 'Flow' : 'Subflow'} {#if flowInfo?.label} : {flowInfo.label} {/if}
{getStepProgress(rootJob, modules.length)}
timelineAvailableWidths[flowId] ?? 0, (v) => (timelineAvailableWidths[flowId] = v) } > {#if timelineItems && showTimeline && timelineMin != undefined && timelineTotal} {@const moduleItems = [ { started_at: rootJob?.started_at ? new Date(rootJob.started_at).getTime() : undefined, duration_ms: rootJob?.['duration_ms'] ?? timelineTotal, id: flowId } ]}
0 && isExpanded(`flow-${flowId}`)} onZoom={() => { useRelativeTimeline = !useRelativeTimeline }} zoom={useRelativeTimeline ? 'in' : 'out'} isJobFailure={(id) => isJobFailure(id)} /> {/if}
{#if flowInfo?.jobId && !isReplay}
e.stopPropagation()} >
{/if}
{/snippet} {#if level === 0 || isExpanded(`flow-${flowId}`, rootJob?.type === 'QueuedJob')}
{#if flowInfo?.logs}
{/if}
{#if showResultsInputs && flowInfo?.inputs && Object.keys(flowInfo.inputs).length > 0}
{#snippet label()}
Inputs
{/snippet} {#if isExpanded(`flow-${flowId}-input`)}
{/if}
{/if} {#if modules.length > 0} {#each modules as module (module.id)} {@const isLeafStep = !hasSubflows(module)} {@const status = localModuleStates[module.id]?.type} {@const isRunning = status === 'InProgress' || status === 'WaitingForExecutor'} {@const hasEmptySubflowValue = hasEmptySubflow(module.id, module.value.type)} {@const isCollapsible = !hasEmptySubflowValue} {@const jobId = localModuleStates[module.id]?.job_id} {@const moduleItems = timelineItems?.[module.id]} {@const branchChosen = module.value.type === 'branchone' ? (localModuleStates[module.id]?.branchChosen ?? 0) : undefined}
{#snippet label()}
{@render stepIcon( module.value.type, status as FlowStatusModule['type'], flowInfo?.parentsWithErrors.has(module.id) )}
{#if mode === 'aiagent'} {#if module.summary} Tool call: {module.summary} {:else} Message {/if} {:else} {module.id} {/if}
{#if mode === 'flow'} {#if module.value.type === 'forloopflow'} For loop {:else if module.value.type === 'whileloopflow'} While loop {:else if module.value.type === 'branchall'} Branch to all {:else if module.value.type === 'branchone'} Branch to one {:else if module.value.type === 'flow'} Subflow {:else} Step {/if} {/if} {#if module.summary && mode !== 'aiagent'} : {module.summary} {/if} {#if hasEmptySubflowValue}
{#if module.value.type === 'forloopflow' || module.value.type === 'whileloopflow'} (empty loop) {:else if module.value.type === 'branchall' || module.value.type === 'branchone'} (no branch) {/if}
{/if}
{#if !hasEmptySubflowValue && localModuleStates[module.id]?.flow_jobs && (module.value.type === 'forloopflow' || module.value.type === 'whileloopflow')}
e.stopPropagation()}>
{#if module.value.type === 'forloopflow'} {`/${localModuleStates[module.id]?.iteration_total ?? 0}`} {/if}
{/if}
timelineAvailableWidths[module.id] ?? 0, (v) => (timelineAvailableWidths[module.id] = v) } > {#if timelineMin != undefined && timelineTotal && moduleItems && showTimeline}
{ if ( module.value.type !== 'forloopflow' && module.value.type !== 'whileloopflow' ) { return } const index = localModuleStates[module.id]?.flow_jobs?.indexOf(id) ?? undefined if (index !== undefined) { onSelectedIteration?.({ id, index, manuallySet: true, moduleId: module.id }) } }} showIterations={localModuleStates[module.id]?.flow_jobs} selectedIndex={getSelectedIndex(module.id, moduleItems)} idToIterationIndex={(id) => { return localModuleStates[module.id]?.flow_jobs?.indexOf(id) }} isJobFailure={() => isJobFailure(undefined, module.id)} /> {/if}
{#if isLeafStep && jobId && !isReplay}
{/if}
{/snippet} {#if isCollapsible && isExpanded(module.id, isRunning)} {@const subflows = getSubflows(module)}
{#each subflows as subflow, idx} {@const subflowJob = getSubflowJob( module.id, idx, branchChosen, module.value.type )}
{/each} {#if subflows.length === 0} {@const args = localModuleStates[module.id]?.args} {@const logs = localModuleStates[module.id]?.logs} {@const result = localModuleStates[module.id]?.result} {@const jobId = localModuleStates[module.id]?.job_id} {#if showResultsInputs && isLeafStep && args && Object.keys(args).length > 0}
{#snippet label()}
Input
{/snippet} {#if isExpanded(`${module.id}-input`)}
{/if}
{/if} {#if logs}
select(`${module.id}-logs`)}>
{:else if jobId && !hasSubflows(module)}
No logs available
{/if} {#if showResultsInputs && isLeafStep && result !== undefined && (status === 'Success' || status === 'Failure')}
{#snippet label()}
Result
{/snippet} {#if isExpanded(`${module.id}-result`)}
{/if}
{/if} {/if}
{/if}
{/each} {/if} {#if showResultsInputs && flowInfo?.result !== undefined && rootJob?.type === 'CompletedJob'}
{#snippet label()}
Results
{/snippet}
{/if}
{/if}
{/if} {#snippet flowIcon(status: FlowStatusModule['type'] | undefined, hasErrors: boolean | undefined)} {@const colorClass = getStatusColor(status)}
{#if hasErrors && status !== 'Failure'}
!
{/if}
{/snippet} {#snippet stepIcon( stepType: string | undefined, status: FlowStatusModule['type'] | undefined, hasErrors: boolean | undefined )} {@const colorClass = getStatusColor(status)} {@const animationClass = status === 'InProgress' ? 'animate-pulse' : ''} {@const classes = `${colorClass} ${animationClass} flex-shrink-0`}
{#if stepType === 'flow'}
{:else if stepType === 'forloopflow' || stepType === 'whileloopflow'}
{:else if stepType === 'branchall' || stepType === 'branchone'}
{:else}
{/if} {#if hasErrors && status !== 'Failure'}
!
{/if}
{/snippet}