windmill-components 1.542.4 → 1.550.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/package/common.d.ts +4 -1
  2. package/package/components/AIAgentLogViewer.svelte +1 -1
  3. package/package/components/ArgEnum.svelte +14 -5
  4. package/package/components/ArgInput.svelte +23 -15
  5. package/package/components/ArgInput.svelte.d.ts +1 -1
  6. package/package/components/ChannelSelector.svelte +92 -18
  7. package/package/components/ChannelSelector.svelte.d.ts +2 -0
  8. package/package/components/ConnectionSection.svelte +12 -1
  9. package/package/components/Dev.svelte +18 -5
  10. package/package/components/Dev.svelte.d.ts +23 -1
  11. package/package/components/DisplayResult.svelte +36 -23
  12. package/package/components/DropdownV2.svelte +8 -2
  13. package/package/components/DropdownV2.svelte.d.ts +1 -0
  14. package/package/components/DynamicInput.svelte +10 -10
  15. package/package/components/EditableSchemaForm.svelte +21 -7
  16. package/package/components/EditorSettings.svelte +11 -9
  17. package/package/components/ErrorOrRecoveryHandler.svelte +14 -20
  18. package/package/components/FlowHistoryJobPicker.svelte +3 -0
  19. package/package/components/FlowHistoryJobPicker.svelte.d.ts +1 -0
  20. package/package/components/FlowJobResult.svelte +5 -5
  21. package/package/components/FlowLogRow.svelte +2 -2
  22. package/package/components/FlowLogViewer.svelte +228 -57
  23. package/package/components/FlowLogViewer.svelte.d.ts +16 -5
  24. package/package/components/FlowLogViewerWrapper.svelte +56 -3
  25. package/package/components/FlowLogViewerWrapper.svelte.d.ts +4 -3
  26. package/package/components/FlowLoopIterationPreview.svelte +4 -4
  27. package/package/components/FlowMetadata.svelte +3 -4
  28. package/package/components/FlowMetadata.svelte.d.ts +4 -18
  29. package/package/components/FlowPreviewContent.svelte +9 -3
  30. package/package/components/FlowPreviewContent.svelte.d.ts +1 -1
  31. package/package/components/FlowStatusViewer.svelte +62 -59
  32. package/package/components/FlowStatusViewer.svelte.d.ts +2 -2
  33. package/package/components/FlowStatusViewerInner.svelte +186 -94
  34. package/package/components/FlowStatusViewerInner.svelte.d.ts +10 -3
  35. package/package/components/FlowTimeline.svelte +110 -131
  36. package/package/components/FlowTimeline.svelte.d.ts +13 -4
  37. package/package/components/FlowTimelineBar.svelte +227 -0
  38. package/package/components/FlowTimelineBar.svelte.d.ts +24 -0
  39. package/package/components/InputTransformForm.svelte +119 -3
  40. package/package/components/InputTransformForm.svelte.d.ts +3 -0
  41. package/package/components/InputTransformSchemaForm.svelte +5 -1
  42. package/package/components/InputTransformSchemaForm.svelte.d.ts +2 -0
  43. package/package/components/InstanceSetting.svelte +17 -42
  44. package/package/components/InstanceSettings.svelte +12 -21
  45. package/package/components/JobArgs.svelte +15 -16
  46. package/package/components/JobArgs.svelte.d.ts +4 -18
  47. package/package/components/JobLoader.svelte +23 -42
  48. package/package/components/JobLoader.svelte.d.ts +2 -0
  49. package/package/components/JobStatus.svelte +1 -1
  50. package/package/components/JobStatus.svelte.d.ts +4 -18
  51. package/package/components/ModulePreviewResultViewer.svelte +1 -7
  52. package/package/components/NextcloudSetting.svelte +6 -1
  53. package/package/components/Password.svelte +7 -11
  54. package/package/components/Password.svelte.d.ts +5 -20
  55. package/package/components/PasswordArgInput.svelte +35 -15
  56. package/package/components/PasswordArgInput.svelte.d.ts +4 -18
  57. package/package/components/QueuePosition.svelte +6 -2
  58. package/package/components/RunForm.svelte +5 -14
  59. package/package/components/S3ArrayHelperButton.svelte +12 -0
  60. package/package/components/S3ArrayHelperButton.svelte.d.ts +8 -0
  61. package/package/components/ScriptEditor.svelte +5 -6
  62. package/package/components/StringTypeNarrowing.svelte +39 -24
  63. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  64. package/package/components/TeamSelector.svelte +83 -37
  65. package/package/components/TeamSelector.svelte.d.ts +0 -1
  66. package/package/components/apps/components/buttons/AppButton.svelte +11 -1
  67. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +13 -4
  68. package/package/components/apps/components/display/table/SyncColumnDefs.svelte +2 -2
  69. package/package/components/apps/components/display/table/utils.js +1 -1
  70. package/package/components/apps/components/helpers/RefreshButton.svelte +5 -1
  71. package/package/components/apps/components/helpers/RunnableComponent.svelte +0 -2
  72. package/package/components/apps/components/helpers/RunnableWrapper.svelte.d.ts +1 -0
  73. package/package/components/apps/components/layout/AppTabs.svelte +116 -71
  74. package/package/components/apps/components/layout/AppTabs.svelte.d.ts +1 -0
  75. package/package/components/apps/editor/component/ComponentInner.svelte +1 -0
  76. package/package/components/apps/editor/component/components.d.ts +16 -1
  77. package/package/components/apps/editor/component/components.js +22 -2
  78. package/package/components/apps/editor/settingsPanel/ComponentPanel.svelte +2 -0
  79. package/package/components/apps/editor/settingsPanel/GridTab.svelte +19 -1
  80. package/package/components/apps/editor/settingsPanel/GridTab.svelte.d.ts +3 -1
  81. package/package/components/apps/editor/settingsPanel/GridTabHidden.svelte +52 -0
  82. package/package/components/apps/editor/settingsPanel/GridTabHidden.svelte.d.ts +9 -0
  83. package/package/components/auditLogs/AuditLogsFilters.svelte +6 -0
  84. package/package/components/auditLogs/AuditLogsTable.svelte +17 -7
  85. package/package/components/auditLogs/AuditLogsTable.svelte.d.ts +1 -0
  86. package/package/components/common/CloseButton.svelte +2 -2
  87. package/package/components/common/CloseButton.svelte.d.ts +1 -0
  88. package/package/components/common/layout/List.svelte +3 -7
  89. package/package/components/common/layout/List.svelte.d.ts +7 -29
  90. package/package/components/common/popup/PopupV2.svelte +8 -25
  91. package/package/components/common/popup/PopupV2.svelte.d.ts +4 -2
  92. package/package/components/common/table/ScriptRow.svelte +22 -2
  93. package/package/components/copilot/FlowCopilotInputsModal.svelte +26 -23
  94. package/package/components/copilot/chat/AIChatManager.svelte.js +3 -2
  95. package/package/components/copilot/chat/ProviderModelSelector.svelte +1 -1
  96. package/package/components/copilot/chat/flow/FlowAIChat.svelte +4 -2
  97. package/package/components/copilot/chat/script/core.d.ts +4 -4
  98. package/package/components/copilot/chat/script/core.js +93 -34
  99. package/package/components/copilot/lib.d.ts +1 -0
  100. package/package/components/copilot/lib.js +6 -3
  101. package/package/components/custom_ui.d.ts +2 -0
  102. package/package/components/flows/FlowProgressBar.svelte +16 -16
  103. package/package/components/flows/FlowProgressBar.svelte.d.ts +7 -22
  104. package/package/components/flows/content/FlowInputsQuick.svelte +3 -2
  105. package/package/components/flows/content/FlowInputsQuick.svelte.d.ts +1 -0
  106. package/package/components/flows/content/FlowModuleComponent.svelte +24 -1
  107. package/package/components/flows/flowInfers.js +34 -8
  108. package/package/components/flows/flowStore.d.ts +4 -1
  109. package/package/components/flows/map/FlowJobsMenu.svelte +3 -3
  110. package/package/components/flows/map/FlowJobsMenu.svelte.d.ts +1 -1
  111. package/package/components/flows/map/InsertModuleButton.svelte +4 -14
  112. package/package/components/flows/map/InsertModuleButton.svelte.d.ts +0 -1
  113. package/package/components/flows/map/InsertModuleInner.svelte +17 -20
  114. package/package/components/flows/map/MapItem.svelte +1 -1
  115. package/package/components/flows/pickers/PickHubScriptQuick.svelte +38 -52
  116. package/package/components/flows/pickers/PickHubScriptQuick.svelte.d.ts +1 -0
  117. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte +27 -15
  118. package/package/components/flows/pickers/WorkspaceScriptPickerQuick.svelte.d.ts +1 -0
  119. package/package/components/flows/propPicker/OutputPicker.svelte +2 -0
  120. package/package/components/git_sync/DetectionFlow.svelte +33 -44
  121. package/package/components/git_sync/DetectionFlow.svelte.d.ts +1 -0
  122. package/package/components/git_sync/GitSyncContext.svelte.d.ts +22 -0
  123. package/package/components/git_sync/GitSyncContext.svelte.js +145 -5
  124. package/package/components/git_sync/GitSyncModeDisplay.svelte +14 -0
  125. package/package/components/git_sync/GitSyncModeDisplay.svelte.d.ts +9 -0
  126. package/package/components/git_sync/GitSyncRepositoryCard.svelte +365 -253
  127. package/package/components/git_sync/GitSyncRepositoryCard.svelte.d.ts +10 -1
  128. package/package/components/git_sync/GitSyncSection.svelte +134 -14
  129. package/package/components/git_sync/PullWorkspaceModal.svelte +24 -32
  130. package/package/components/git_sync/PushWorkspaceModal.svelte +24 -32
  131. package/package/components/graph/model.d.ts +5 -5
  132. package/package/components/graph/renderers/edges/EmptyEdge.svelte +3 -10
  133. package/package/components/graph/renderers/edges/EmptyEdge.svelte.d.ts +4 -18
  134. package/package/components/graph/renderers/nodes/AIToolNode.svelte +2 -2
  135. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +5 -10
  136. package/package/components/home/ItemsList.svelte +1 -1
  137. package/package/components/jobs/JobProgressBar.svelte +27 -21
  138. package/package/components/jobs/JobProgressBar.svelte.d.ts +9 -24
  139. package/package/components/meltComponents/MenuSingleItem.svelte +3 -8
  140. package/package/components/meltComponents/MenuSingleItem.svelte.d.ts +0 -3
  141. package/package/components/meltComponents/Popover.svelte +3 -2
  142. package/package/components/meltComponents/Popover.svelte.d.ts +1 -0
  143. package/package/components/meltComponents/Tooltip.svelte +1 -1
  144. package/package/components/progressBar/ProgressBar.svelte +39 -53
  145. package/package/components/progressBar/ProgressBar.svelte.d.ts +11 -26
  146. package/package/components/runs/JobsLoader.svelte +1 -1
  147. package/package/components/runs/NoWorkerWithTagWarning.svelte +3 -3
  148. package/package/components/runs/NoWorkerWithTagWarning.svelte.d.ts +1 -1
  149. package/package/components/schema/AddPropertyV2.svelte +7 -4
  150. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  151. package/package/components/select/MultiSelect.svelte +2 -2
  152. package/package/components/select/MultiSelect.svelte.d.ts +1 -0
  153. package/package/components/settings/WorkspaceUserSettings.svelte +92 -1
  154. package/package/components/sidebar/MenuLink.svelte +2 -1
  155. package/package/components/sidebar/MenuLink.svelte.d.ts +1 -0
  156. package/package/components/sidebar/SidebarContent.svelte +27 -27
  157. package/package/components/table/Cell.svelte +7 -14
  158. package/package/components/table/Cell.svelte.d.ts +13 -35
  159. package/package/components/triggers/AddTriggersButton.svelte +1 -0
  160. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte +1 -1
  161. package/package/components/triggers/gcp/GcpTriggerEditorConfigSection.svelte.d.ts +2 -1
  162. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +28 -5
  163. package/package/components/triggers/gcp/utils.js +1 -0
  164. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +1 -0
  165. package/package/components/triggers/webhook/WebhooksConfigSection.svelte +143 -63
  166. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +22 -0
  167. package/package/components/triggers/websocket/utils.js +1 -0
  168. package/package/components/workspaceSettings/AISettings.svelte +8 -2
  169. package/package/components/workspaceSettings/AISettings.svelte.d.ts +2 -1
  170. package/package/components/workspaceSettings/ModelTokenLimits.svelte +165 -0
  171. package/package/components/workspaceSettings/ModelTokenLimits.svelte.d.ts +8 -0
  172. package/package/components/workspaceSettings/StorageSettings.svelte +123 -51
  173. package/package/gen/core/OpenAPI.js +1 -1
  174. package/package/gen/schemas.gen.d.ts +141 -16
  175. package/package/gen/schemas.gen.js +144 -16
  176. package/package/gen/services.gen.d.ts +62 -42
  177. package/package/gen/services.gen.js +131 -82
  178. package/package/gen/types.gen.d.ts +218 -144
  179. package/package/hubPaths.json +2 -1
  180. package/package/services/JobManager.js +10 -7
  181. package/package/stores.d.ts +1 -0
  182. package/package/stores.js +6 -3
  183. package/package/timelineCompute.svelte.d.ts +21 -0
  184. package/package/timelineCompute.svelte.js +113 -0
  185. package/package/utils.d.ts +15 -8
  186. package/package/utils.js +62 -12
  187. package/package/workspace_settings.d.ts +13 -8
  188. package/package/workspace_settings.js +46 -11
  189. package/package.json +2 -2
@@ -29,8 +29,8 @@ import JobLoader from './JobLoader.svelte';
29
29
  import { writable } from 'svelte/store';
30
30
  import { AI_TOOL_CALL_PREFIX, AI_TOOL_MESSAGE_PREFIX, getToolCallId } from './graph/renderers/nodes/AIToolNode.svelte';
31
31
  import JobAssetsViewer from './assets/JobAssetsViewer.svelte';
32
- let { flowStateStore, retryStatus, suspendStatus, hideDownloadInGraph, hideTimeline, hideNodeDefinition, hideDownloadLogs, hideJobId } = getContext('FlowStatusViewer');
33
- let { jobId, initialJob = undefined, workspaceId = undefined, flowJobIds = undefined, innerModule = undefined, render = true, isOwner = false, selectedNode = $bindable(undefined), globalModuleStates, globalDurationStatuses = [], globalIterationBounds, updateRecursiveRefreshFn = undefined, isSelectedBranch = true, isSubflow = false, reducedPolling = false, wideResults = false, hideFlowResult = false, workspace = $workspaceStore, prefix = undefined, topModuleStates = undefined, refreshGlobal, updateGlobalRefresh, subflowParentsGlobalModuleStates = [], subflowParentsDurationStatuses = [], isForloopSelected = false, job = $bindable(undefined), rightColumnSelect = $bindable('timeline'), localModuleStates = $bindable({}), localDurationStatuses = $bindable({}), customUi, onResultStreamUpdate = undefined, graphTabOpen, isNodeSelected, loadExtraLogs = undefined, onStart = undefined, onJobsLoaded = undefined, onDone = undefined, toolCallStore } = $props();
32
+ let { flowState: flowStateStore, retryStatus, suspendStatus, hideDownloadInGraph, hideTimeline, hideNodeDefinition, hideDownloadLogs, hideJobId } = getContext('FlowStatusViewer');
33
+ let { jobId, initialJob = undefined, workspaceId = undefined, flowJobIds = undefined, innerModule = undefined, render = true, isOwner = false, selectedNode = $bindable(undefined), globalModuleStates, globalDurationStatuses = [], updateRecursiveRefreshFn = undefined, isSelectedBranch = true, isSubflow = false, reducedPolling = false, wideResults = false, hideFlowResult = false, workspace = $workspaceStore, prefix = undefined, topModuleStates = undefined, refreshGlobal, updateGlobalRefresh, subflowParentsGlobalModuleStates = [], subflowParentsDurationStatuses = [], isForloopSelected = false, job = $bindable(undefined), rightColumnSelect = $bindable('timeline'), localModuleStates = $bindable({}), localDurationStatuses = $bindable({}), customUi, onResultStreamUpdate = undefined, graphTabOpen, isNodeSelected, loadExtraLogs = undefined, onStart = undefined, onJobsLoaded = undefined, onDone = undefined, toolCallStore } = $props();
34
34
  let getTopModuleStates = $derived(topModuleStates ?? localModuleStates);
35
35
  let resultStreams = $state({});
36
36
  if (onResultStreamUpdate == undefined) {
@@ -218,15 +218,24 @@ function setModuleState(key, value, force, keepType) {
218
218
  }
219
219
  }
220
220
  }
221
- function setDurationStatusByJob(key, id, value) {
222
- if (!deepEqual(localDurationStatuses[key]?.byJob[id], value)) {
223
- localDurationStatuses[key].byJob[id] = value;
221
+ function setDurationStatusByJob(key, id, value, overwrite = false) {
222
+ if (!deepEqual(localDurationStatuses[key]?.byJob?.[id], value)) {
223
+ if (localDurationStatuses[key]?.byJob == undefined) {
224
+ localDurationStatuses[key] = { byJob: {} };
225
+ }
226
+ localDurationStatuses[key].byJob = {
227
+ [id]: value,
228
+ ...(overwrite ? {} : (localDurationStatuses[key].byJob ?? {}))
229
+ };
224
230
  globalDurationStatuses.forEach((s) => {
225
- s[key].byJob[id] = value;
231
+ s[key].byJob = { [id]: value, ...(overwrite ? {} : (s[key].byJob ?? {})) };
226
232
  });
227
233
  if (prefix) {
228
234
  subflowParentsDurationStatuses.forEach((s) => {
229
- s[buildSubflowKey(key, prefix)].byJob[id] = value;
235
+ s[buildSubflowKey(key, prefix)].byJob = {
236
+ [id]: value,
237
+ ...(overwrite ? {} : (s[buildSubflowKey(key, prefix)].byJob ?? {}))
238
+ };
230
239
  });
231
240
  }
232
241
  }
@@ -272,6 +281,29 @@ function updateStatus(status) {
272
281
  delete suspendStatus.val[jobId ?? ''];
273
282
  }
274
283
  }
284
+ function updateDurationStatuses(key, durationStatuses) {
285
+ if (localDurationStatuses[key] == undefined) {
286
+ localDurationStatuses[key] = { byJob: {} };
287
+ }
288
+ localDurationStatuses[key].byJob = durationStatuses;
289
+ globalDurationStatuses.forEach((s) => {
290
+ if (s[key] == undefined) {
291
+ s[key] = { byJob: {} };
292
+ }
293
+ s[key].byJob = durationStatuses;
294
+ });
295
+ if (prefix) {
296
+ subflowParentsDurationStatuses.forEach((s) => {
297
+ if (s[key] == undefined) {
298
+ s[key] = { byJob: {} };
299
+ }
300
+ s[key].byJob = durationStatuses;
301
+ });
302
+ }
303
+ }
304
+ let jobMissingStartedAt = {};
305
+ let lastSelectedLoopSwitch;
306
+ let selectedLoopSwitchTimeout = undefined;
275
307
  function updateInnerModules() {
276
308
  if (localModuleStates) {
277
309
  innerModules?.forEach((mod, i) => {
@@ -309,7 +341,7 @@ function updateInnerModules() {
309
341
  branchChosen: mod.branch_chosen.type == 'default' ? 0 : (mod.branch_chosen.branch ?? 0) + 1
310
342
  }
311
343
  : {};
312
- console.debug('updateInnerModules', mod.id, mod.type, branchChosen);
344
+ // console.debug('updateInnerModules', mod.id, mod.type, branchChosen)
313
345
  setModuleState(mod.id ?? '', {
314
346
  type: mod.type,
315
347
  ...branchChosen
@@ -318,13 +350,107 @@ function updateInnerModules() {
318
350
  else if (isForloopSelected) {
319
351
  setModuleState(mod.id ?? '', {}, true);
320
352
  }
321
- if (mod.flow_jobs_success || mod.flow_jobs) {
353
+ if (mod.flow_jobs_success || mod.flow_jobs_duration || mod.flow_jobs) {
322
354
  setModuleState(mod.id ?? '', {
323
355
  flow_jobs_success: mod.flow_jobs_success,
356
+ flow_jobs_duration: mod.flow_jobs_duration,
324
357
  flow_jobs: mod.flow_jobs,
325
358
  iteration_total: mod.iterator?.itered?.length ?? mod.flow_jobs?.length
326
359
  });
327
360
  }
361
+ if (mod.flow_jobs_duration && mod.flow_jobs) {
362
+ let key = buildSubflowKey(mod.id ?? '', prefix);
363
+ let durationStatuses = Object.fromEntries(mod.flow_jobs.map((flowJobId, idx) => {
364
+ let started_at_str = mod.flow_jobs_duration?.started_at?.[idx];
365
+ let started_at = started_at_str ? new Date(started_at_str).getTime() : undefined;
366
+ let duration_ms = mod.flow_jobs_duration?.duration_ms?.[idx];
367
+ if (started_at == undefined) {
368
+ let missingStartedAt = jobMissingStartedAt[flowJobId];
369
+ if (missingStartedAt != 'P') {
370
+ started_at = missingStartedAt;
371
+ }
372
+ }
373
+ else {
374
+ delete jobMissingStartedAt[flowJobId];
375
+ }
376
+ return [
377
+ flowJobId,
378
+ {
379
+ created_at: started_at,
380
+ started_at: started_at,
381
+ duration_ms: duration_ms
382
+ }
383
+ ];
384
+ }));
385
+ let missingStartedAtIds = Object.keys(durationStatuses)
386
+ .filter((id) => durationStatuses[id].created_at == undefined && jobMissingStartedAt[id] != 'P')
387
+ .slice(0, 100);
388
+ updateDurationStatuses(key, durationStatuses);
389
+ if (missingStartedAtIds.length > 0) {
390
+ missingStartedAtIds.forEach((id) => {
391
+ jobMissingStartedAt[id] = 'P';
392
+ });
393
+ JobService.getStartedAtByIds({
394
+ workspace: workspaceId ?? $workspaceStore ?? '',
395
+ requestBody: missingStartedAtIds
396
+ })
397
+ .then((jobs) => {
398
+ let lastStarted = undefined;
399
+ let anySet = false;
400
+ let nDurationStatuses = localDurationStatuses[key]?.byJob;
401
+ missingStartedAtIds.forEach((id, idx) => {
402
+ const startedAt = jobs[idx];
403
+ const time = startedAt ? new Date(startedAt).getTime() : undefined;
404
+ if (time) {
405
+ jobMissingStartedAt[id] = time;
406
+ }
407
+ else {
408
+ delete jobMissingStartedAt[id];
409
+ }
410
+ if (nDurationStatuses && time) {
411
+ if (!nDurationStatuses[id]?.duration_ms) {
412
+ anySet = true;
413
+ lastStarted = id;
414
+ nDurationStatuses[id] = {
415
+ created_at: time,
416
+ started_at: time
417
+ };
418
+ }
419
+ }
420
+ });
421
+ if (anySet) {
422
+ updateDurationStatuses(key, nDurationStatuses);
423
+ selectedLoopSwitchTimeout && clearTimeout(selectedLoopSwitchTimeout);
424
+ function setSelectedLoopSwitch() {
425
+ if (lastStarted) {
426
+ let position = mod.flow_jobs?.indexOf(lastStarted);
427
+ if (position != undefined) {
428
+ lastSelectedLoopSwitch = new Date().getTime();
429
+ console.log('setSelectedLoopSwitch', position, lastStarted);
430
+ setIteration(position, lastStarted, false, mod.id ?? '', true);
431
+ }
432
+ }
433
+ }
434
+ if (lastSelectedLoopSwitch &&
435
+ new Date().getTime() - lastSelectedLoopSwitch < 3000) {
436
+ selectedLoopSwitchTimeout = setTimeout(() => {
437
+ setSelectedLoopSwitch();
438
+ }, 2000);
439
+ }
440
+ else {
441
+ console.log('setSelectedLoopSwitch');
442
+ setSelectedLoopSwitch();
443
+ }
444
+ }
445
+ })
446
+ .catch((e) => {
447
+ console.error(`Could not load inner module duration status for job ${mod.job}`, e);
448
+ });
449
+ }
450
+ else {
451
+ setIteration(0, mod.flow_jobs?.[0] ?? '', false, mod.id ?? '', true);
452
+ }
453
+ }
328
454
  if (mod.agent_actions && mod.id) {
329
455
  setModuleState(mod.id, {
330
456
  agent_actions: mod.agent_actions
@@ -430,7 +556,6 @@ async function updateJobId() {
430
556
  flowTimeline?.reset();
431
557
  timeout && clearTimeout(timeout);
432
558
  innerModules = undefined;
433
- console.log('updateJobId', jobId);
434
559
  if (flowJobIds) {
435
560
  let modId = flowJobIds?.moduleId ?? '';
436
561
  if (localDurationStatuses[modId] == undefined) {
@@ -442,10 +567,6 @@ async function updateJobId() {
442
567
  x[prefixed] = { byJob: {} };
443
568
  }
444
569
  });
445
- globalIterationBounds[prefixed] = {
446
- iteration_from: flowJobIds?.branchall ? 0 : Math.max(flowJobIds.flowJobs.length - 20, 0),
447
- iteration_total: flowJobIds?.length
448
- };
449
570
  }
450
571
  else {
451
572
  recursiveRefresh = {};
@@ -497,7 +618,7 @@ function onJobsLoadedInner(mod, job, force) {
497
618
  setDurationStatusByJob(id, job.id, {
498
619
  created_at: job.created_at ? new Date(job.created_at).getTime() : undefined,
499
620
  started_at
500
- });
621
+ }, true);
501
622
  }
502
623
  else {
503
624
  const parent_module = mod['parent_module'];
@@ -515,6 +636,7 @@ function onJobsLoadedInner(mod, job, force) {
515
636
  started_at: started_at,
516
637
  flow_jobs: mod.flow_jobs,
517
638
  flow_jobs_success: mod.flow_jobs_success,
639
+ flow_jobs_duration: mod.flow_jobs_duration,
518
640
  iteration_total: mod.iterator?.itered?.length,
519
641
  retries: mod?.failed_retries?.length,
520
642
  skipped: mod.skipped,
@@ -525,7 +647,7 @@ function onJobsLoadedInner(mod, job, force) {
525
647
  created_at: job.created_at ? new Date(job.created_at).getTime() : undefined,
526
648
  started_at,
527
649
  duration_ms: job['duration_ms']
528
- });
650
+ }, true);
529
651
  }
530
652
  }
531
653
  }
@@ -605,6 +727,7 @@ function innerJobLoaded(jobLoaded, j, clicked, force) {
605
727
  started_at,
606
728
  flow_jobs: flowJobIds?.flowJobs,
607
729
  flow_jobs_success: flowJobIds?.flowJobsSuccess,
730
+ flow_jobs_duration: flowJobIds?.flowJobsDuration,
608
731
  iteration_total: flowJobIds?.length,
609
732
  duration_ms: undefined
610
733
  };
@@ -626,18 +749,20 @@ function innerJobLoaded(jobLoaded, j, clicked, force) {
626
749
  }
627
750
  }
628
751
  setModuleState(modId, v, force, true);
629
- if (jobLoaded.type == 'QueuedJob') {
630
- setDurationStatusByJob(modId, job_id, {
631
- created_at,
632
- started_at
633
- });
634
- }
635
- else if (jobLoaded.type == 'CompletedJob') {
636
- setDurationStatusByJob(modId, job_id, {
637
- created_at,
638
- started_at,
639
- duration_ms: jobLoaded.duration_ms
640
- });
752
+ if (innerModule?.type == 'branchall') {
753
+ if (jobLoaded.type == 'QueuedJob') {
754
+ setDurationStatusByJob(modId, job_id, {
755
+ created_at,
756
+ started_at
757
+ }, false);
758
+ }
759
+ else if (jobLoaded.type == 'CompletedJob') {
760
+ setDurationStatusByJob(modId, job_id, {
761
+ created_at,
762
+ started_at,
763
+ duration_ms: jobLoaded.duration_ms
764
+ }, false);
765
+ }
641
766
  }
642
767
  if (jobLoaded.job_kind == 'script' || isScriptPreview(jobLoaded.job_kind)) {
643
768
  let id = undefined;
@@ -652,14 +777,6 @@ function innerJobLoaded(jobLoaded, j, clicked, force) {
652
777
  }
653
778
  }
654
779
  let flowTimeline = $state();
655
- function loadPreviousIters(innerKey, lenToAdd) {
656
- let key = buildSubflowKey(innerKey, prefix);
657
- if (globalIterationBounds[key]) {
658
- globalIterationBounds[key].iteration_from =
659
- (globalIterationBounds[key]?.iteration_from ?? 0) - lenToAdd;
660
- }
661
- // updateSlicedListJobIds()
662
- }
663
780
  let stepDetail = $state(undefined);
664
781
  let storedListJobs = $state({});
665
782
  let selectedToolCall = $state(undefined);
@@ -679,9 +796,11 @@ function removeFailureNode(id, parent_module) {
679
796
  }
680
797
  }
681
798
  function allModulesForTimeline(modules, expandedSubflows) {
682
- const ids = dfs(modules, (x) => x.id, { skipToolNodes: true });
799
+ const ids = dfs(modules, (x) => ({ id: x.id, type: x.value.type }), {
800
+ skipToolNodes: true
801
+ });
683
802
  function rec(ids, prefix) {
684
- return ids.concat(ids.flatMap((id) => {
803
+ return ids.concat(ids.flatMap(({ id, type }) => {
685
804
  let fms = expandedSubflows[id];
686
805
  let oid = id.split(':').pop();
687
806
  if (!oid) {
@@ -689,7 +808,10 @@ function allModulesForTimeline(modules, expandedSubflows) {
689
808
  }
690
809
  let nprefix = buildPrefix(prefix, oid);
691
810
  return fms
692
- ? rec(dfs(fms, (x) => (x.id.startsWith('subflow:') ? x.id : buildSubflowKey(x.id, nprefix)), { skipToolNodes: true }), nprefix)
811
+ ? rec(dfs(fms, (x) => ({
812
+ id: x.id.startsWith('subflow:') ? x.id : buildSubflowKey(x.id, nprefix),
813
+ type: x.value.type
814
+ }), { skipToolNodes: true }), nprefix)
693
815
  : [];
694
816
  }));
695
817
  }
@@ -810,32 +932,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
810
932
  <div class="h-8" />
811
933
  {/if} -->
812
934
  {#if isListJob}
813
- {@const sliceFrom =
814
- globalIterationBounds[buildSubflowKey(flowJobIds?.moduleId ?? '', prefix)]
815
- ?.iteration_from ?? 0}
816
- {@const lenToAdd = Math.min(20, sliceFrom)}
817
- {#if (flowJobIds?.flowJobs.length ?? 0) > 20 && lenToAdd > 0}
818
- {@const allToAdd = (flowJobIds?.length ?? 0) - sliceFrom}
819
- <p class="text-tertiary italic text-xs">
820
- For performance reasons, only the last 20 items are shown by default <button
821
- class="text-primary underline ml-4"
822
- onclick={() => {
823
- loadPreviousIters(flowJobIds?.moduleId ?? '', lenToAdd)
824
- }}
825
- >Load {lenToAdd} prior
826
- </button>
827
- {#if allToAdd > 0 && allToAdd > lenToAdd}
828
- {sliceFrom}
829
- <button
830
- class="text-primary underline ml-4"
831
- onclick={() => {
832
- loadPreviousIters(flowJobIds?.moduleId ?? '', allToAdd)
833
- }}
834
- >Load {allToAdd} prior
835
- </button>
836
- {/if}
837
- </p>
838
- {/if}
839
935
  {#if render}
840
936
  <div class="w-full h-full border rounded-sm bg-surface p-1 overflow-auto">
841
937
  <DisplayResult
@@ -885,9 +981,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
885
981
  style="min-height: {minTabHeight}px"
886
982
  >
887
983
  {#if isListJob}
888
- {@const sliceFrom =
889
- globalIterationBounds[buildSubflowKey(flowJobIds?.moduleId ?? '', prefix)]
890
- ?.iteration_from ?? 0}
891
984
  <h3 class="text-md leading-6 font-bold text-tertiary border-b mb-4">
892
985
  Subflows ({flowJobIds?.flowJobs.length})
893
986
  </h3>
@@ -930,7 +1023,7 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
930
1023
  </span>
931
1024
  </Button>
932
1025
  {/if}
933
- {#if j >= sliceFrom || forloop_selected == loopJobId}
1026
+ {#if forloop_selected == loopJobId || innerModule?.type == 'branchall'}
934
1027
  {@const forloopIsSelected =
935
1028
  forloop_selected == loopJobId ||
936
1029
  (innerModule?.type != 'forloopflow' && innerModule?.type != 'whileloopflow')}
@@ -971,7 +1064,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
971
1064
  {onResultStreamUpdate}
972
1065
  graphTabOpen={selected == 'graph' && graphTabOpen}
973
1066
  isNodeSelected={forloop_selected == loopJobId}
974
- {globalIterationBounds}
975
1067
  toolCallStore={{
976
1068
  getStoredToolCallJob: (storeKey: string) =>
977
1069
  toolCallStore?.getStoredToolCallJob(forLoopStoreKeyPrefix + storeKey),
@@ -989,14 +1081,17 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
989
1081
  {/if}
990
1082
  {/each}
991
1083
  </div>
992
- {:else if innerModules && innerModules.length > 0 && (job.raw_flow?.modules.length ?? 0) > 0}
1084
+ {:else if innerModules && innerModules.length > 0 && ((job.raw_flow?.modules.length ?? 0) > 0 || innerModules[0]?.id == 'preprocessor')}
993
1085
  {@const hasPreprocessor = innerModules[0]?.id == 'preprocessor' ? 1 : 0}
1086
+ {@const isPreprocessorOnly = hasPreprocessor && (job.raw_flow?.modules.length ?? 0) === 0}
1087
+ <!-- if the flow is preprocessor only, we should only display the first innerModule: the second one is a placeholder added when running empty flows -->
1088
+ {@const modules = isPreprocessorOnly ? [innerModules[0]] : (innerModules ?? [])}
994
1089
  <ul class="w-full">
995
1090
  <h3 class="text-md leading-6 font-bold text-primary border-b mb-4 py-2">
996
1091
  Step-by-step
997
1092
  </h3>
998
1093
 
999
- {#each innerModules ?? [] as mod, i}
1094
+ {#each modules as mod, i}
1000
1095
  {#if render}
1001
1096
  <div class="line w-8 h-10"></div>
1002
1097
  <h3 class="text-tertiary mb-2 w-full">
@@ -1064,7 +1159,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1064
1159
  {onResultStreamUpdate}
1065
1160
  graphTabOpen={selected == 'graph' && graphTabOpen}
1066
1161
  isNodeSelected={retry_selected == failedRetry}
1067
- {globalIterationBounds}
1068
1162
  />
1069
1163
  </div>
1070
1164
  {/each}
@@ -1079,7 +1173,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1079
1173
  globalModuleStates={[]}
1080
1174
  {updateGlobalRefresh}
1081
1175
  globalDurationStatuses={[]}
1082
- {globalIterationBounds}
1083
1176
  prefix={buildPrefix(prefix, mod.id ?? '')}
1084
1177
  subflowParentsGlobalModuleStates={[
1085
1178
  localModuleStates,
@@ -1127,6 +1220,7 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1127
1220
  moduleId: mod.id ?? '',
1128
1221
  flowJobs: mod.flow_jobs,
1129
1222
  flowJobsSuccess: mod.flow_jobs_success ?? [],
1223
+ flowJobsDuration: mod.flow_jobs_duration,
1130
1224
  length: mod.iterator?.itered?.length ?? mod.flow_jobs.length,
1131
1225
  branchall: job?.raw_flow?.modules?.[i]?.value?.type == 'branchall'
1132
1226
  }
@@ -1142,7 +1236,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1142
1236
  {onResultStreamUpdate}
1143
1237
  graphTabOpen={selected == 'graph' && graphTabOpen}
1144
1238
  isNodeSelected={localModuleStates?.[selectedNode ?? '']?.job_id == mod.job}
1145
- {globalIterationBounds}
1146
1239
  {toolCallStore}
1147
1240
  />
1148
1241
  {#if mod.agent_actions && mod.agent_actions.length > 0 && mod.id}
@@ -1212,7 +1305,6 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1212
1305
  graphTabOpen={selected == 'graph' && graphTabOpen}
1213
1306
  isNodeSelected={localModuleStates?.[toolCallId]?.job_id ==
1214
1307
  agentAction.job_id}
1215
- {globalIterationBounds}
1216
1308
  />
1217
1309
  {/if}
1218
1310
  {/if}
@@ -1232,20 +1324,22 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1232
1324
  <div class="p-2 text-tertiary text-sm italic">Empty flow</div>
1233
1325
  {/if}
1234
1326
  </div>
1235
- <div
1236
- class="{selected != 'logs' ? 'hidden' : ''} mx-auto"
1237
- bind:clientHeight={tabsHeight.logsHeight}
1238
- style="min-height: {minTabHeight}px"
1239
- >
1240
- <FlowLogViewerWrapper
1241
- {job}
1242
- {localModuleStates}
1243
- {workspaceId}
1244
- {render}
1245
- {onSelectedIteration}
1246
- />
1247
- </div>
1248
- {#if selected == 'assets' && render}
1327
+ {#if selected == 'logs' && render}
1328
+ <div
1329
+ class="mx-auto"
1330
+ bind:clientHeight={tabsHeight.logsHeight}
1331
+ style="min-height: {minTabHeight}px"
1332
+ >
1333
+ <FlowLogViewerWrapper
1334
+ {job}
1335
+ {localModuleStates}
1336
+ {localDurationStatuses}
1337
+ {workspaceId}
1338
+ {render}
1339
+ {onSelectedIteration}
1340
+ />
1341
+ </div>
1342
+ {:else if selected == 'assets' && render}
1249
1343
  <div
1250
1344
  class="p-2"
1251
1345
  bind:clientHeight={tabsHeight.assetsHeight}
@@ -1348,6 +1442,8 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1348
1442
  </Tabs>
1349
1443
  {#if rightColumnSelect == 'timeline'}
1350
1444
  <FlowTimeline
1445
+ {localModuleStates}
1446
+ {onSelectedIteration}
1351
1447
  selfWaitTime={job?.self_wait_time_ms}
1352
1448
  aggregateWaitTime={job?.aggregate_wait_time_ms}
1353
1449
  flowDone={job?.['success'] != undefined}
@@ -1357,11 +1453,7 @@ let minTabHeight = $derived(Math.max(tabsHeight.sequenceHeight, tabsHeight.logsH
1357
1453
  expandedSubflows ?? {}
1358
1454
  )}
1359
1455
  buildSubflowKey={(key) => buildSubflowKey(key, prefix)}
1360
- {globalIterationBounds}
1361
1456
  durationStatuses={localDurationStatuses}
1362
- decreaseIterationFrom={(key, amount) => {
1363
- loadPreviousIters(key, amount)
1364
- }}
1365
1457
  />
1366
1458
  {:else if rightColumnSelect == 'node_status'}
1367
1459
  <div class="pt-2 grow flex flex-col">
@@ -1,6 +1,6 @@
1
1
  import FlowStatusViewerInner from './FlowStatusViewerInner.svelte';
2
2
  import { type Job, type FlowModuleValue, type CompletedJob } from '../gen';
3
- import { type DurationStatus, type GlobalIterationBounds, type GraphModuleState } from './graph';
3
+ import { type DurationStatus, type GraphModuleState } from './graph';
4
4
  interface Props {
5
5
  jobId: string;
6
6
  initialJob?: Job | undefined;
@@ -9,6 +9,10 @@ interface Props {
9
9
  moduleId: string;
10
10
  flowJobs: string[];
11
11
  flowJobsSuccess: (boolean | undefined)[];
12
+ flowJobsDuration: {
13
+ started_at?: (string | undefined)[];
14
+ duration_ms?: (number | undefined)[];
15
+ } | undefined;
12
16
  length: number;
13
17
  branchall?: boolean;
14
18
  } | undefined;
@@ -18,7 +22,6 @@ interface Props {
18
22
  selectedNode?: string | undefined;
19
23
  globalModuleStates: Record<string, GraphModuleState>[];
20
24
  globalDurationStatuses?: Record<string, DurationStatus>[];
21
- globalIterationBounds: Record<string, GlobalIterationBounds>;
22
25
  isSelectedBranch?: boolean;
23
26
  isSubflow?: boolean;
24
27
  reducedPolling?: boolean;
@@ -65,6 +68,10 @@ interface Props {
65
68
  addToolCallToLoad: (storeKey: string) => void;
66
69
  };
67
70
  }
68
- declare const FlowStatusViewerInner: import("svelte").Component<Props, {}, "job" | "localModuleStates" | "selectedNode" | "rightColumnSelect" | "localDurationStatuses">;
71
+ export type FlowModuleForTimeline = {
72
+ id: string;
73
+ type: FlowModuleValue['type'];
74
+ };
75
+ declare const FlowStatusViewerInner: import("svelte").Component<Props, {}, "job" | "localModuleStates" | "localDurationStatuses" | "selectedNode" | "rightColumnSelect">;
69
76
  type FlowStatusViewerInner = ReturnType<typeof FlowStatusViewerInner>;
70
77
  export default FlowStatusViewerInner;