windmill-components 1.522.0 → 1.531.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 (271) hide show
  1. package/package/components/AIAgentLogViewer.svelte +123 -0
  2. package/package/components/AIAgentLogViewer.svelte.d.ts +13 -0
  3. package/package/components/AppConnectInner.svelte +10 -10
  4. package/package/components/AutoscalingConfigEditor.svelte +76 -2
  5. package/package/components/Dev.svelte +12 -28
  6. package/package/components/DiffEditor.svelte +6 -3
  7. package/package/components/DiffEditor.svelte.d.ts +1 -0
  8. package/package/components/DisplayResult.svelte +16 -10
  9. package/package/components/DisplayResult.svelte.d.ts +1 -0
  10. package/package/components/EditableSchemaForm.svelte +5 -2
  11. package/package/components/Editor.svelte +26 -8
  12. package/package/components/Editor.svelte.d.ts +1 -1
  13. package/package/components/EditorBar.svelte +25 -5
  14. package/package/components/EditorSettings.svelte +6 -0
  15. package/package/components/FirstStepInputs.svelte +2 -2
  16. package/package/components/FlowBuilder.svelte +18 -36
  17. package/package/components/FlowGraphViewerStep.svelte +7 -0
  18. package/package/components/FlowJobResult.svelte +15 -63
  19. package/package/components/FlowJobResult.svelte.d.ts +10 -4
  20. package/package/components/FlowLogViewer.svelte +660 -0
  21. package/package/components/FlowLogViewer.svelte.d.ts +34 -0
  22. package/package/components/FlowLogViewerWrapper.svelte +52 -0
  23. package/package/components/FlowLogViewerWrapper.svelte.d.ts +21 -0
  24. package/package/components/FlowLoopIterationPreview.svelte +3 -3
  25. package/package/components/FlowPreviewContent.svelte +4 -5
  26. package/package/components/FlowPreviewContent.svelte.d.ts +7 -7
  27. package/package/components/FlowPreviewResult.svelte +4 -5
  28. package/package/components/FlowPreviewResult.svelte.d.ts +3 -5
  29. package/package/components/FlowStatusViewer.svelte +28 -16
  30. package/package/components/FlowStatusViewer.svelte.d.ts +19 -27
  31. package/package/components/FlowStatusViewerInner.svelte +483 -296
  32. package/package/components/FlowStatusViewerInner.svelte.d.ts +27 -33
  33. package/package/components/FlowTimeline.svelte +11 -13
  34. package/package/components/FlowTimeline.svelte.d.ts +6 -5
  35. package/package/components/HighlightCode.svelte +4 -1
  36. package/package/components/IconedResourceType.svelte +9 -5
  37. package/package/components/JobLoader.svelte +61 -8
  38. package/package/components/JobLoader.svelte.d.ts +9 -1
  39. package/package/components/LogViewer.svelte +8 -2
  40. package/package/components/LogViewer.svelte.d.ts +1 -0
  41. package/package/components/LogViewerHeader.svelte +32 -0
  42. package/package/components/LogViewerHeader.svelte.d.ts +8 -0
  43. package/package/components/ModulePreviewForm.svelte +10 -6
  44. package/package/components/ModulePreviewResultViewer.svelte +16 -0
  45. package/package/components/ModulePreviewResultViewer.svelte.d.ts +1 -1
  46. package/package/components/ModuleTest.svelte +59 -16
  47. package/package/components/RelativeLineNumbers.svelte +16 -0
  48. package/package/components/RelativeLineNumbers.svelte.d.ts +18 -0
  49. package/package/components/ResourceEditor.svelte +9 -4
  50. package/package/components/ScriptBuilder.svelte +13 -11
  51. package/package/components/ScriptEditor.svelte +2 -2
  52. package/package/components/SimpleEditor.svelte +10 -4
  53. package/package/components/SimpleEditor.svelte.d.ts +1 -0
  54. package/package/components/TemplateEditor.svelte +1 -1
  55. package/package/components/UserSettings.svelte +4 -4
  56. package/package/components/apps/components/display/AppAccordionList.svelte +1 -1
  57. package/package/components/apps/components/display/AppCarouselList.svelte +10 -8
  58. package/package/components/apps/components/display/AppJobIdFlowStatus.svelte +3 -3
  59. package/package/components/apps/components/display/table/AppAggridTable.svelte +2 -2
  60. package/package/components/apps/components/helpers/HiddenComponent.svelte +0 -1
  61. package/package/components/apps/components/helpers/InputValue.svelte +6 -1
  62. package/package/components/apps/components/helpers/NonRunnableComponent.svelte +8 -4
  63. package/package/components/apps/components/helpers/NonRunnableComponent.svelte.d.ts +1 -1
  64. package/package/components/apps/components/helpers/RunnableComponent.svelte +7 -8
  65. package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +1 -1
  66. package/package/components/apps/components/helpers/RunnableWrapper.svelte +12 -3
  67. package/package/components/apps/components/helpers/RunnableWrapper.svelte.d.ts +1 -1
  68. package/package/components/apps/components/inputs/AppCodeInputComponent.svelte +0 -5
  69. package/package/components/apps/components/layout/AppConditionalWrapper.svelte +1 -1
  70. package/package/components/apps/components/layout/AppContainer.svelte +1 -1
  71. package/package/components/apps/components/layout/AppDecisionTree.svelte +31 -20
  72. package/package/components/apps/components/layout/AppDrawer.svelte +1 -1
  73. package/package/components/apps/components/layout/AppList.svelte +9 -8
  74. package/package/components/apps/components/layout/AppModal.svelte +1 -1
  75. package/package/components/apps/components/layout/AppSplitpanes.svelte +5 -2
  76. package/package/components/apps/components/layout/AppStepper.svelte +9 -5
  77. package/package/components/apps/components/layout/AppTabs.svelte +2 -2
  78. package/package/components/apps/editor/AppJobsDrawer.svelte +2 -2
  79. package/package/components/apps/editor/GridEditor.svelte +24 -19
  80. package/package/components/apps/editor/GridEditor.svelte.d.ts +4 -1
  81. package/package/components/apps/editor/GridViewer.svelte +1 -1
  82. package/package/components/apps/editor/SubGridEditor.svelte +7 -11
  83. package/package/components/apps/editor/SubGridEditor.svelte.d.ts +3 -19
  84. package/package/components/apps/editor/appUtils.js +17 -68
  85. package/package/components/apps/editor/component/ComponentInner.svelte +845 -694
  86. package/package/components/apps/editor/component/componentCallbacks.svelte.js +8 -1
  87. package/package/components/apps/editor/contextPanel/components/OutputHeader.svelte +9 -46
  88. package/package/components/apps/editor/settingsPanel/DecisionTreeGraphEditor.svelte +29 -43
  89. package/package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte +2 -1
  90. package/package/components/apps/editor/settingsPanel/InputsSpecEditor.svelte.d.ts +1 -0
  91. package/package/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte +2 -2
  92. package/package/components/apps/editor/settingsPanel/inputEditor/EvalV2InputEditor.svelte.d.ts +1 -0
  93. package/package/components/apps/svelte-grid/Grid.svelte +23 -25
  94. package/package/components/apps/svelte-grid/Grid.svelte.d.ts +21 -9
  95. package/package/components/apps/svelte-grid/MoveResize.svelte +13 -15
  96. package/package/components/apps/svelte-grid/MoveResize.svelte.d.ts +17 -24
  97. package/package/components/apps/utils.d.ts +2 -0
  98. package/package/components/apps/utils.js +22 -0
  99. package/package/components/auditLogs/AuditLogsFilters.svelte.d.ts +1 -1
  100. package/package/components/common/fileDownload/FileDownload.svelte +1 -3
  101. package/package/components/common/fileDownload/FileDownload.svelte.d.ts +4 -18
  102. package/package/components/common/languageIcons/LanguageIcon.svelte +5 -2
  103. package/package/components/copilot/FlowInlineScriptAIButton.svelte +58 -0
  104. package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +3 -0
  105. package/package/components/copilot/MetadataGen.svelte +19 -1
  106. package/package/components/copilot/MetadataGen.svelte.d.ts +1 -1
  107. package/package/components/copilot/ScriptGen.svelte +23 -31
  108. package/package/components/copilot/ScriptGen.svelte.d.ts +0 -1
  109. package/package/components/copilot/autocomplete/Autocompletor.js +2 -0
  110. package/package/components/copilot/chat/AIChatDisplay.svelte +4 -4
  111. package/package/components/copilot/chat/AIChatInput.svelte +29 -6
  112. package/package/components/copilot/chat/AIChatManager.svelte.js +110 -26
  113. package/package/components/copilot/chat/AIChatMessage.svelte +3 -0
  114. package/package/components/copilot/chat/ToolContentDisplay.svelte +84 -0
  115. package/package/components/copilot/chat/ToolContentDisplay.svelte.d.ts +11 -0
  116. package/package/components/copilot/chat/ToolExecutionDisplay.svelte +105 -0
  117. package/package/components/copilot/chat/ToolExecutionDisplay.svelte.d.ts +7 -0
  118. package/package/components/copilot/chat/api/apiTools.d.ts +7 -0
  119. package/package/components/copilot/chat/api/apiTools.js +192 -0
  120. package/package/components/copilot/chat/api/core.d.ts +7 -0
  121. package/package/components/copilot/chat/api/core.js +61 -0
  122. package/package/components/copilot/chat/flow/FlowAIChat.svelte +4 -6
  123. package/package/components/copilot/chat/flow/core.js +213 -42
  124. package/package/components/copilot/chat/flow/utils.js +3 -0
  125. package/package/components/copilot/chat/monaco-adapter.d.ts +1 -1
  126. package/package/components/copilot/chat/monaco-adapter.js +10 -4
  127. package/package/components/copilot/chat/navigator/core.d.ts +1 -1
  128. package/package/components/copilot/chat/navigator/core.js +20 -22
  129. package/package/components/copilot/chat/script/core.d.ts +11 -3
  130. package/package/components/copilot/chat/script/core.js +92 -15
  131. package/package/components/copilot/chat/shared.d.ts +30 -3
  132. package/package/components/copilot/chat/shared.js +228 -9
  133. package/package/components/copilot/lib.d.ts +1 -1
  134. package/package/components/copilot/lib.js +15 -6
  135. package/package/components/custom_ui.d.ts +2 -0
  136. package/package/components/details/DetailPageLayout.svelte +34 -33
  137. package/package/components/flow_builder.d.ts +1 -2
  138. package/package/components/flows/FlowEditor.svelte +3 -3
  139. package/package/components/flows/FlowEditor.svelte.d.ts +7 -6
  140. package/package/components/flows/common/FlowCard.svelte +2 -2
  141. package/package/components/flows/common/FlowCard.svelte.d.ts +1 -0
  142. package/package/components/flows/common/FlowCardHeader.svelte +13 -4
  143. package/package/components/flows/common/FlowCardHeader.svelte.d.ts +1 -0
  144. package/package/components/flows/content/BranchPredicateEditor.svelte +4 -7
  145. package/package/components/flows/content/BranchPredicateEditor.svelte.d.ts +12 -11
  146. package/package/components/flows/content/FlowConstants.svelte +3 -3
  147. package/package/components/flows/content/FlowEditorPanel.svelte +3 -3
  148. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +2 -4
  149. package/package/components/flows/content/FlowInputsQuick.svelte +2 -1
  150. package/package/components/flows/content/FlowLoop.svelte +2 -2
  151. package/package/components/flows/content/FlowModuleComponent.svelte +130 -108
  152. package/package/components/flows/content/FlowModuleComponent.svelte.d.ts +1 -0
  153. package/package/components/flows/content/FlowModuleEarlyStop.svelte +2 -2
  154. package/package/components/flows/content/FlowModuleSkip.svelte +1 -1
  155. package/package/components/flows/content/FlowModuleSleep.svelte +1 -1
  156. package/package/components/flows/content/FlowModuleSuspend.svelte +1 -1
  157. package/package/components/flows/content/FlowModuleWrapper.svelte +15 -5
  158. package/package/components/flows/content/FlowModuleWrapper.svelte.d.ts +1 -0
  159. package/package/components/flows/content/FlowResult.svelte +2 -3
  160. package/package/components/flows/content/FlowResult.svelte.d.ts +2 -4
  161. package/package/components/flows/content/FlowWhileLoop.svelte +1 -1
  162. package/package/components/flows/dfs.d.ts +3 -1
  163. package/package/components/flows/dfs.js +5 -1
  164. package/package/components/flows/flowInfers.js +78 -0
  165. package/package/components/flows/flowState.d.ts +2 -3
  166. package/package/components/flows/flowState.js +2 -2
  167. package/package/components/flows/flowStateUtils.svelte.d.ts +4 -4
  168. package/package/components/flows/flowStateUtils.svelte.js +14 -13
  169. package/package/components/flows/flowStore.d.ts +3 -4
  170. package/package/components/flows/header/FlowPreviewButtons.svelte +2 -1
  171. package/package/components/flows/header/FlowYamlEditor.svelte +10 -1
  172. package/package/components/flows/map/FlowGraphPreviewButton.svelte +1 -1
  173. package/package/components/flows/map/FlowJobsMenu.svelte +7 -3
  174. package/package/components/flows/map/FlowJobsMenu.svelte.d.ts +1 -0
  175. package/package/components/flows/map/FlowModuleSchemaItem.svelte +12 -12
  176. package/package/components/flows/map/FlowModuleSchemaMap.svelte +26 -19
  177. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +6 -4
  178. package/package/components/flows/map/InsertModuleInner.svelte +9 -1
  179. package/package/components/flows/map/InsertModuleInner.svelte.d.ts +1 -0
  180. package/package/components/flows/map/MapItem.svelte +4 -2
  181. package/package/components/flows/pickers/TopLevelNode.svelte +4 -1
  182. package/package/components/flows/propPicker/InputPickerInner.svelte +5 -4
  183. package/package/components/flows/propPicker/OutputBadge.svelte +11 -9
  184. package/package/components/flows/propPicker/OutputPickerInner.svelte +10 -1
  185. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +1 -1
  186. package/package/components/flows/testSteps.svelte.d.ts +3 -2
  187. package/package/components/flows/testSteps.svelte.js +26 -23
  188. package/package/components/flows/types.d.ts +1 -1
  189. package/package/components/flows/utils.d.ts +3 -5
  190. package/package/components/flows/utils.js +3 -4
  191. package/package/components/git_sync/GitSyncContext.svelte.js +2 -1
  192. package/package/components/graph/FlowGraphV2.svelte +44 -24
  193. package/package/components/graph/FlowGraphV2.svelte.d.ts +5 -2
  194. package/package/components/graph/graphBuilder.svelte.d.ts +49 -17
  195. package/package/components/graph/graphBuilder.svelte.js +30 -14
  196. package/package/components/graph/model.d.ts +9 -6
  197. package/package/components/graph/renderers/edges/BaseEdge.svelte +3 -3
  198. package/package/components/graph/renderers/edges/BaseEdge.svelte.d.ts +2 -3
  199. package/package/components/graph/renderers/nodes/AIToolNode.svelte +234 -0
  200. package/package/components/graph/renderers/nodes/AIToolNode.svelte.d.ts +24 -0
  201. package/package/components/graph/renderers/nodes/AssetNode.svelte +15 -10
  202. package/package/components/graph/renderers/nodes/AssetNode.svelte.d.ts +18 -1
  203. package/package/components/graph/renderers/nodes/BranchAllEndNode.svelte +1 -1
  204. package/package/components/graph/renderers/nodes/BranchAllStart.svelte +1 -1
  205. package/package/components/graph/renderers/nodes/BranchOneStart.svelte +1 -1
  206. package/package/components/graph/renderers/nodes/ForLoopEndNode.svelte +2 -2
  207. package/package/components/graph/renderers/nodes/ForLoopStartNode.svelte +1 -1
  208. package/package/components/graph/renderers/nodes/ModuleNode.svelte +21 -21
  209. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +64 -0
  210. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte.d.ts +7 -0
  211. package/package/components/graph/renderers/nodes/branchOneEndNode.svelte +1 -1
  212. package/package/components/icons/RubyIcon.svelte +656 -0
  213. package/package/components/icons/RubyIcon.svelte.d.ts +7 -0
  214. package/package/components/instanceSettings.js +9 -0
  215. package/package/components/modulesTest.svelte.d.ts +6 -3
  216. package/package/components/modulesTest.svelte.js +32 -0
  217. package/package/components/preview/FlowPreviewStatus.svelte +3 -1
  218. package/package/components/raw_apps/RawAppEditor.svelte +27 -26
  219. package/package/components/raw_apps/RawAppEditor.svelte.d.ts +17 -17
  220. package/package/components/runs/{JobPreview.svelte → JobRunsPreview.svelte} +1 -4
  221. package/package/components/runs/{JobPreview.svelte.d.ts → JobRunsPreview.svelte.d.ts} +3 -3
  222. package/package/components/runs/RunRow.svelte +5 -1
  223. package/package/components/schema/AddProperty.svelte +41 -36
  224. package/package/components/schema/AddProperty.svelte.d.ts +2 -2
  225. package/package/components/schema/AddPropertyV2.svelte +41 -37
  226. package/package/components/schema/AddPropertyV2.svelte.d.ts +1 -1
  227. package/package/components/schema/FlowPropertyEditor.svelte +8 -6
  228. package/package/components/search/RunsSearch.svelte +1 -1
  229. package/package/components/settings/CreateToken.svelte +132 -12
  230. package/package/components/settings/CreateToken.svelte.d.ts +3 -20
  231. package/package/components/settings/TokenDisplay.svelte +18 -42
  232. package/package/components/settings/TokenDisplay.svelte.d.ts +0 -1
  233. package/package/components/settings/TokensTable.svelte +2 -4
  234. package/package/components/settings/TokensTable.svelte.d.ts +3 -19
  235. package/package/components/settings/WorkspaceUserSettings.svelte +428 -69
  236. package/package/components/sidebar/MenuButton.svelte +12 -10
  237. package/package/components/stepHistoryLoader.svelte.d.ts +2 -2
  238. package/package/components/stepHistoryLoader.svelte.js +7 -12
  239. package/package/components/triggers/http/OpenAPISpecGenerator.svelte +2 -2
  240. package/package/components/tutorials/FlowBuilderTutorialBranchOne.svelte +1 -1
  241. package/package/components/tutorials/FlowBuilderTutorialForLoop.svelte +4 -4
  242. package/package/components/tutorials/utils.js +3 -0
  243. package/package/components/worker_group.d.ts +4 -1
  244. package/package/components/worker_group.js +3 -2
  245. package/package/editorLangUtils.d.ts +1 -1
  246. package/package/editorLangUtils.js +2 -0
  247. package/package/editorUtils.d.ts +2 -1
  248. package/package/editorUtils.js +2 -1
  249. package/package/gen/core/OpenAPI.js +1 -1
  250. package/package/gen/schemas.gen.d.ts +296 -8
  251. package/package/gen/schemas.gen.js +364 -70
  252. package/package/gen/services.gen.d.ts +118 -16
  253. package/package/gen/services.gen.js +226 -19
  254. package/package/gen/types.gen.d.ts +660 -16
  255. package/package/hubPaths.json +7 -4
  256. package/package/infer.js +10 -1
  257. package/package/monaco_workers/graphql.worker.bundle.js +144 -110
  258. package/package/script_helpers.d.ts +3 -0
  259. package/package/script_helpers.js +58 -3
  260. package/package/scripts.d.ts +1 -1
  261. package/package/scripts.js +3 -2
  262. package/package/stores.d.ts +2 -0
  263. package/package/stores.js +2 -0
  264. package/package/svelte5Utils.svelte.d.ts +16 -0
  265. package/package/svelte5Utils.svelte.js +26 -0
  266. package/package/utils.d.ts +1 -1
  267. package/package.json +20 -19
  268. package/package/components/AllFlowLogs.svelte +0 -31
  269. package/package/components/AllFlowLogs.svelte.d.ts +0 -8
  270. package/package/components/copilot/chat/navigator/apiTools.d.ts +0 -68
  271. package/package/components/copilot/chat/navigator/apiTools.js +0 -258
@@ -4,7 +4,7 @@ import { workspaceStore } from '../stores';
4
4
  import { base } from '../base';
5
5
  import FlowJobResult from './FlowJobResult.svelte';
6
6
  import DisplayResult from './DisplayResult.svelte';
7
- import { createEventDispatcher, getContext, setContext, tick, untrack } from 'svelte';
7
+ import { getContext, setContext, tick, untrack } from 'svelte';
8
8
  import { onDestroy } from 'svelte';
9
9
  import { Badge, Button, Skeleton, Tab } from './common';
10
10
  import Tabs from './common/tabs/Tabs.svelte';
@@ -16,18 +16,20 @@ import { ChevronDown, Hourglass } from 'lucide-svelte';
16
16
  import { deepEqual } from 'fast-equals';
17
17
  import FlowTimeline from './FlowTimeline.svelte';
18
18
  import { dfs } from './flows/dfs';
19
- import { get, writable } from 'svelte/store';
20
19
  import Alert from './common/alert/Alert.svelte';
21
20
  import FlowGraphViewerStep from './FlowGraphViewerStep.svelte';
22
21
  import FlowGraphV2 from './graph/FlowGraphV2.svelte';
23
22
  import { buildPrefix } from './graph/graphBuilder.svelte';
24
23
  import { parseInputArgsAssets } from './assets/lib';
25
24
  import FlowPreviewResult from './FlowPreviewResult.svelte';
25
+ import FlowLogViewerWrapper from './FlowLogViewerWrapper.svelte';
26
26
  import { createState } from '../svelte5Utils.svelte';
27
27
  import JobLoader from './JobLoader.svelte';
28
- const dispatch = createEventDispatcher();
28
+ import { writable } from 'svelte/store';
29
+ import { AI_TOOL_CALL_PREFIX, AI_TOOL_MESSAGE_PREFIX, getToolCallId } from './graph/renderers/nodes/AIToolNode.svelte';
29
30
  let { flowStateStore, retryStatus, suspendStatus, hideDownloadInGraph, hideTimeline, hideNodeDefinition, hideDownloadLogs, hideJobId } = getContext('FlowStatusViewer');
30
- let { jobId, initialJob = undefined, workspaceId = undefined, flowJobIds = undefined, innerModule = undefined, globalRefreshes = $bindable({}), render = true, isOwner = false, selectedNode = $bindable(undefined), globalModuleStates, globalDurationStatuses, childFlow = false, isSubflow = false, reducedPolling = false, wideResults = false, hideFlowResult = false, workspace = $workspaceStore, prefix = undefined, subflowParentsGlobalModuleStates = [], subflowParentsDurationStatuses = [], isForloopSelected = false, parentRecursiveRefresh = $bindable({}), job = $bindable(undefined), rightColumnSelect = $bindable('timeline'), localModuleStates = writable({}), localDurationStatuses = writable({}), customUi, onResultStreamUpdate = undefined } = $props();
31
+ 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 } = $props();
32
+ let getTopModuleStates = $derived(topModuleStates ?? localModuleStates);
31
33
  let resultStreams = $state({});
32
34
  if (onResultStreamUpdate == undefined) {
33
35
  onResultStreamUpdate = ({ jobId, result_stream }) => {
@@ -35,6 +37,11 @@ if (onResultStreamUpdate == undefined) {
35
37
  };
36
38
  }
37
39
  let recursiveRefresh = $state({});
40
+ let updateRecursiveRefreshInner = (childJobId, updateFn) => {
41
+ if (childJobId) {
42
+ recursiveRefresh[childJobId] = updateFn;
43
+ }
44
+ };
38
45
  // Add support for the input args assets shown as an asset node
39
46
  const _flowGraphAssetsCtx = getContext('FlowGraphAssetContext');
40
47
  let extendedFlowGraphAssetsCtx = $state(createState(clone(_flowGraphAssetsCtx)));
@@ -68,180 +75,179 @@ let timeout = undefined;
68
75
  let expandedSubflows = $state({});
69
76
  let selectedId = writable(selectedNode);
70
77
  function onFlowModuleId() {
71
- if (globalRefreshes) {
72
- let modId = flowJobIds?.moduleId;
73
- if (modId) {
74
- globalRefreshes[buildSubflowKey(modId, prefix)] = async (clear, root) => {
75
- await refresh(clear, root); // refresh(true, loopJob)
76
- };
77
- }
78
+ let modId = flowJobIds?.moduleId;
79
+ if (modId) {
80
+ let prefixedId = buildSubflowKey(modId, prefix);
81
+ updateGlobalRefresh(prefixedId, async (clear, root) => {
82
+ // console.debug('updateGlobalRefreshInner refresh', prefixedId, clear, root)
83
+ await refresh(clear, root); // refresh(true, loopJob)
84
+ });
78
85
  }
79
86
  }
80
87
  function updateModuleStates(moduleState, key, newValue, keepType) {
81
- const state = get(moduleState);
82
88
  if (newValue.selectedForloop != undefined &&
83
- state[key]?.selectedForloop != undefined &&
84
- newValue.selectedForloop != state[key].selectedForloop) {
89
+ moduleState[key]?.selectedForloop != undefined &&
90
+ newValue.selectedForloop != moduleState[key].selectedForloop) {
91
+ let newState = { ...moduleState[key] };
85
92
  if (newValue.type == 'InProgress' &&
86
- state[key]?.type != 'InProgress' &&
87
- !(keepType && (state[key]?.type === 'Success' || state[key]?.type === 'Failure'))) {
88
- moduleState.update((state) => {
89
- state[key].type = 'InProgress';
90
- return state;
91
- });
93
+ moduleState[key]?.type != 'InProgress' &&
94
+ !(keepType &&
95
+ (moduleState[key]?.type === 'Success' || moduleState[key]?.type === 'Failure'))) {
96
+ newState.type = 'InProgress';
92
97
  }
93
- if (state[key]?.job_id != newValue.job_id ||
94
- !deepEqual(state[key]?.args, newValue.args) ||
95
- !deepEqual(state[key]?.result, newValue.result)) {
96
- moduleState.update((state) => {
97
- state[key].args = newValue.args;
98
- state[key].result = newValue.result;
99
- state[key].job_id = newValue.job_id;
100
- return state;
101
- });
98
+ else if (['Success', 'Failure'].includes(newValue.type)) {
99
+ newState.type = newValue.type;
102
100
  }
101
+ if (moduleState[key]?.job_id != newValue.job_id ||
102
+ !deepEqual(moduleState[key]?.args, newValue.args) ||
103
+ !deepEqual(moduleState[key]?.result, newValue.result)) {
104
+ newState.args = newValue.args;
105
+ newState.result = newValue.result;
106
+ newState.job_id = newValue.job_id;
107
+ }
108
+ moduleState[key] = newState;
103
109
  return;
104
110
  }
105
- if (state[key]?.selectedForLoopSetManually) {
111
+ if (moduleState[key]?.selectedForLoopSetManually) {
106
112
  if (newValue.selectedForloop != undefined &&
107
- state[key]?.selectedForloop != newValue.selectedForloop) {
108
- return state;
113
+ moduleState[key]?.selectedForloop != newValue.selectedForloop) {
114
+ return moduleState;
109
115
  }
110
116
  else {
111
117
  newValue.selectedForLoopSetManually = true;
112
- newValue.selectedForloopIndex = state[key]?.selectedForloopIndex;
113
- newValue.selectedForloop = state[key]?.selectedForloop;
118
+ newValue.selectedForloopIndex = moduleState[key]?.selectedForloopIndex;
119
+ newValue.selectedForloop = moduleState[key]?.selectedForloop;
114
120
  }
115
121
  }
116
- else if (state[key]?.selectedForloopIndex != undefined) {
117
- newValue.selectedForloopIndex = state[key]?.selectedForloopIndex;
118
- newValue.selectedForloop = state[key]?.selectedForloop;
122
+ else if (moduleState[key]?.selectedForloopIndex != undefined) {
123
+ newValue.selectedForloopIndex = moduleState[key]?.selectedForloopIndex;
124
+ newValue.selectedForloop = moduleState[key]?.selectedForloop;
119
125
  }
120
- if (keepType && (state[key]?.type == 'Success' || state[key]?.type == 'Failure')) {
121
- newValue.type = state[key].type;
126
+ if (keepType && (moduleState[key]?.type == 'Success' || moduleState[key]?.type == 'Failure')) {
127
+ newValue.type = moduleState[key].type;
122
128
  }
123
- if (!deepEqual(state[key], newValue)) {
124
- moduleState.update((state) => {
125
- state[key] = newValue;
126
- return state;
127
- });
129
+ if (!deepEqual(moduleState[key], newValue)) {
130
+ // console.debug('updateModuleStates 2', key, $state.snapshot(moduleState))
131
+ moduleState[key] = newValue;
128
132
  }
129
133
  }
130
134
  function buildSubflowKey(key, prefix) {
131
135
  return prefix ? 'subflow:' + prefix + key : key;
132
136
  }
133
137
  async function refresh(clearLoop, rootJob) {
138
+ console.debug('refresh', clearLoop, rootJob);
134
139
  let modId = flowJobIds?.moduleId;
140
+ let topModuleStates = getTopModuleStates;
135
141
  if (clearLoop) {
136
142
  if (!rootJob) {
137
- let topLevelModuleStates = globalModuleStates?.[globalModuleStates?.length - 1];
138
- if (modId) {
139
- topLevelModuleStates?.update((x) => {
140
- if (modId) {
141
- delete x[modId];
142
- }
143
- return x;
144
- });
143
+ if (modId && topModuleStates) {
144
+ let prefixedId = buildSubflowKey(modId, prefix);
145
+ delete topModuleStates[prefixedId]; // TODO: this is not working
145
146
  }
146
147
  if (subflowParentsGlobalModuleStates.length > 0) {
147
- subflowParentsGlobalModuleStates?.[subflowParentsGlobalModuleStates?.length - 1]?.update((x) => {
148
- for (let mod of innerModules ?? []) {
149
- if (mod.id) {
150
- delete x[buildSubflowKey(mod.id, prefix)];
151
- }
148
+ let subflowModuleStates = subflowParentsGlobalModuleStates?.[subflowParentsGlobalModuleStates?.length - 1];
149
+ for (let mod of innerModules ?? []) {
150
+ if (mod.id) {
151
+ delete subflowModuleStates[buildSubflowKey(mod.id, prefix)];
152
152
  }
153
- return x;
154
- });
153
+ }
155
154
  }
156
155
  else {
157
- topLevelModuleStates?.update((x) => {
158
- for (let mod of innerModules ?? []) {
159
- if (mod.id) {
160
- delete x[mod.id];
161
- }
156
+ for (let mod of innerModules ?? []) {
157
+ if (mod.id && topModuleStates) {
158
+ let prefixedId = buildSubflowKey(mod.id, prefix);
159
+ delete topModuleStates[prefixedId];
162
160
  }
163
- return x;
164
- });
161
+ }
165
162
  }
166
163
  }
167
164
  }
168
165
  else {
169
- let state = modId ? getTopModuleStates()?.[modId] : undefined;
166
+ let state = modId ? topModuleStates?.[buildSubflowKey(modId, prefix)] : undefined;
170
167
  let loopjob = state?.selectedForloop;
171
168
  let njob = flowJobIds && modId && loopjob ? storedListJobs?.[loopjob] : job;
172
169
  if (njob) {
173
- dispatch('jobsLoaded', { job: njob, force: true });
170
+ onJobsLoaded?.({ job: njob, force: true });
174
171
  }
175
172
  }
176
- for (let [k, rec] of Object.entries(recursiveRefresh)) {
177
- if (rootJob != undefined && rootJob != k) {
178
- continue;
179
- }
173
+ let callRec = async (rec) => {
180
174
  await tick();
181
175
  await rec(clearLoop, undefined);
176
+ };
177
+ if (rootJob) {
178
+ let rec = recursiveRefresh[rootJob];
179
+ if (rec) {
180
+ await callRec(rec);
181
+ // console.debug('refresh recursive 1', rec)
182
+ }
183
+ else {
184
+ // console.debug('refresh recursive no rec', rootJob)
185
+ }
186
+ }
187
+ else {
188
+ for (let rec of Object.values(recursiveRefresh)) {
189
+ await callRec(rec);
190
+ // console.debug('refresh recursive 2', rec)
191
+ }
182
192
  }
183
193
  }
184
194
  function updateRecursiveRefresh(jobId) {
185
195
  if (jobId) {
186
- parentRecursiveRefresh[jobId] = async (clear, root) => {
196
+ updateRecursiveRefreshFn?.(jobId, async (clear, root) => {
187
197
  if (globalModuleStates.length > 0 || isSubflow) {
188
198
  await refresh(clear, root);
189
199
  }
190
- };
200
+ });
191
201
  }
192
202
  }
193
203
  function setModuleState(key, value, force, keepType) {
194
- let newValue = { ...($localModuleStates[key] ?? {}), ...value };
195
- if (!deepEqual($localModuleStates[key], value) || force) {
204
+ let newValue = { ...(localModuleStates[key] ?? {}), ...value };
205
+ if (!deepEqual(localModuleStates[key], value) || force) {
206
+ // console.debug('setModuleState', key, force, keepType, $state.snapshot(value))
196
207
  ;
197
208
  [localModuleStates, ...globalModuleStates].forEach((s) => {
198
209
  updateModuleStates(s, key, newValue, keepType);
199
210
  });
200
211
  if (prefix) {
201
- subflowParentsGlobalModuleStates.forEach((s) => updateModuleStates(s, buildSubflowKey(key, prefix), newValue, keepType));
212
+ let prefixedId = buildSubflowKey(key, prefix);
213
+ subflowParentsGlobalModuleStates.forEach((s) => {
214
+ updateModuleStates(s, prefixedId, newValue, keepType);
215
+ });
202
216
  }
203
217
  }
204
218
  }
205
219
  function setDurationStatusByJob(key, id, value) {
206
- if (!deepEqual($localDurationStatuses[key]?.byJob[id], value)) {
207
- $localDurationStatuses[key].byJob[id] = value;
220
+ if (!deepEqual(localDurationStatuses[key]?.byJob[id], value)) {
221
+ localDurationStatuses[key].byJob[id] = value;
208
222
  globalDurationStatuses.forEach((s) => {
209
- s.update((x) => {
210
- x[key].byJob[id] = value;
211
- return x;
212
- });
223
+ s[key].byJob[id] = value;
213
224
  });
214
225
  if (prefix) {
215
226
  subflowParentsDurationStatuses.forEach((s) => {
216
- s.update((x) => {
217
- x[buildSubflowKey(key, prefix)].byJob[id] = value;
218
- return x;
219
- });
227
+ s[buildSubflowKey(key, prefix)].byJob[id] = value;
220
228
  });
221
229
  }
222
230
  }
223
231
  }
224
232
  function initializeByJob(modId) {
225
- if ($localDurationStatuses[modId] == undefined) {
226
- $localDurationStatuses[modId] = { byJob: {} };
233
+ if (localDurationStatuses[modId] == undefined) {
234
+ localDurationStatuses[modId] = { byJob: {} };
227
235
  }
228
- globalDurationStatuses.forEach((x) => x.update((x) => {
236
+ globalDurationStatuses.forEach((x) => {
229
237
  if (x[modId] == undefined) {
230
238
  x[modId] = { byJob: {} };
231
239
  }
232
- return x;
233
- }));
240
+ });
234
241
  if (prefix) {
235
- subflowParentsDurationStatuses.forEach((x) => x.update((x) => {
242
+ subflowParentsDurationStatuses.forEach((x) => {
236
243
  let key = buildSubflowKey(modId, prefix);
237
244
  if (x[key] == undefined) {
238
245
  x[key] = { byJob: {} };
239
246
  }
240
- return x;
241
- }));
247
+ });
242
248
  }
243
249
  }
244
- let innerModules = $state([]);
250
+ let innerModules = $state(undefined);
245
251
  function updateStatus(status) {
246
252
  innerModules =
247
253
  status?.modules?.concat(status.failure_module.type != 'WaitingForPriorSteps' ? status.failure_module : []) ?? [];
@@ -251,29 +257,27 @@ function updateStatus(status) {
251
257
  updateInnerModules();
252
258
  let count = status.retry?.fail_count;
253
259
  if (count) {
254
- $retryStatus[jobId ?? ''] = count;
260
+ retryStatus.val[jobId ?? ''] = count;
255
261
  }
256
- else if ($retryStatus[jobId ?? ''] != undefined) {
257
- delete $retryStatus[jobId ?? ''];
258
- $retryStatus = $retryStatus;
262
+ else if (retryStatus.val[jobId ?? ''] != undefined) {
263
+ delete retryStatus.val[jobId ?? ''];
259
264
  }
260
265
  let jobStatus = job?.flow_status?.modules?.[job?.flow_status.step];
261
266
  if (jobStatus && jobStatus.count != undefined) {
262
- $suspendStatus[jobId ?? ''] = { nb: jobStatus.count, job: job };
267
+ suspendStatus.val[jobId ?? ''] = { nb: jobStatus.count, job: job };
263
268
  }
264
- else if ($suspendStatus[jobId ?? ''] != undefined) {
265
- delete $suspendStatus[jobId ?? ''];
266
- $suspendStatus = $suspendStatus;
269
+ else if (suspendStatus.val[jobId ?? ''] != undefined) {
270
+ delete suspendStatus.val[jobId ?? ''];
267
271
  }
268
272
  }
269
273
  function updateInnerModules() {
270
- if ($localModuleStates) {
271
- innerModules.forEach((mod, i) => {
274
+ if (localModuleStates) {
275
+ innerModules?.forEach((mod, i) => {
272
276
  if (mod.type === 'WaitingForEvents' && innerModules?.[i - 1]?.type === 'Success') {
273
277
  setModuleState(mod.id ?? '', { type: mod.type, args: job?.args, tag: job?.tag });
274
278
  }
275
279
  else if (mod.type === 'WaitingForExecutor' &&
276
- $localModuleStates[mod.id ?? '']?.scheduled_for == undefined) {
280
+ localModuleStates[mod.id ?? '']?.scheduled_for == undefined) {
277
281
  JobService.getJob({
278
282
  workspace: workspaceId ?? $workspaceStore ?? '',
279
283
  id: mod.job ?? '',
@@ -297,12 +301,13 @@ function updateInnerModules() {
297
301
  }
298
302
  else if ((mod.flow_jobs || mod.branch_chosen) &&
299
303
  (mod.type == 'Success' || mod.type == 'Failure') &&
300
- !['Success', 'Failure'].includes($localModuleStates?.[mod.id ?? '']?.type)) {
304
+ !['Success', 'Failure'].includes(localModuleStates?.[mod.id ?? '']?.type)) {
301
305
  let branchChosen = mod.branch_chosen
302
306
  ? {
303
307
  branchChosen: mod.branch_chosen.type == 'default' ? 0 : (mod.branch_chosen.branch ?? 0) + 1
304
308
  }
305
309
  : {};
310
+ console.debug('updateInnerModules', mod.id, mod.type, branchChosen);
306
311
  setModuleState(mod.id ?? '', {
307
312
  type: mod.type,
308
313
  ...branchChosen
@@ -311,9 +316,34 @@ function updateInnerModules() {
311
316
  else if (isForloopSelected) {
312
317
  setModuleState(mod.id ?? '', {}, true);
313
318
  }
314
- if (mod.flow_jobs_success) {
319
+ if (mod.flow_jobs_success || mod.flow_jobs) {
315
320
  setModuleState(mod.id ?? '', {
316
- flow_jobs_success: mod.flow_jobs_success
321
+ flow_jobs_success: mod.flow_jobs_success,
322
+ flow_jobs: mod.flow_jobs,
323
+ iteration_total: mod.iterator?.itered?.length ?? mod.flow_jobs?.length
324
+ });
325
+ }
326
+ if (mod.agent_actions && mod.id) {
327
+ setModuleState(mod.id, {
328
+ agent_actions: mod.agent_actions
329
+ });
330
+ mod.agent_actions.forEach((action, idx) => {
331
+ if (mod.id) {
332
+ if (action.type == 'tool_call') {
333
+ const toolCallId = getToolCallId(idx, mod.id, action.module_id);
334
+ const success = mod.agent_actions_success?.[idx];
335
+ setModuleState(toolCallId, {
336
+ job_id: action.job_id,
337
+ type: success != undefined ? (success ? 'Success' : 'Failure') : 'InProgress'
338
+ });
339
+ }
340
+ else if (action.type == 'message') {
341
+ const toolCallId = getToolCallId(idx, mod.id);
342
+ setModuleState(toolCallId, {
343
+ type: 'Success'
344
+ });
345
+ }
346
+ }
317
347
  });
318
348
  }
319
349
  });
@@ -339,20 +369,20 @@ let notAnonynmous = $state(false);
339
369
  let started = false;
340
370
  let jobLoader = undefined;
341
371
  function setJob(newJob, force) {
342
- if (!deepEqual(job, newJob) || isForloopSelected || force) {
372
+ if (!deepEqual(job, newJob) || isForloopSelected || force || innerModules == undefined) {
343
373
  job = newJob;
344
374
  job?.flow_status && updateStatus(job?.flow_status);
345
- dispatch('jobsLoaded', { job, force: false });
375
+ onJobsLoaded?.({ job, force: false });
346
376
  notAnonynmous = false;
347
377
  if (job?.type == 'CompletedJob' && !destroyed) {
348
- dispatch('done', job);
378
+ onDone?.({ job });
349
379
  }
350
380
  }
351
381
  }
352
382
  async function loadJobInProgress() {
353
383
  if (!started) {
354
384
  started = true;
355
- dispatch('start');
385
+ onStart?.();
356
386
  }
357
387
  if (jobId != '00000000-0000-0000-0000-000000000000') {
358
388
  try {
@@ -368,6 +398,14 @@ async function loadJobInProgress() {
368
398
  },
369
399
  resultStreamUpdate({ id, result_stream }) {
370
400
  onResultStreamUpdate?.({ jobId: id, result_stream });
401
+ },
402
+ loadExtraLogs({ id, logs }) {
403
+ if (id == jobId && job) {
404
+ job.logs = logs;
405
+ }
406
+ if (loadExtraLogs) {
407
+ loadExtraLogs(logs);
408
+ }
371
409
  }
372
410
  });
373
411
  }
@@ -385,61 +423,41 @@ async function loadJobInProgress() {
385
423
  let destroyed = false;
386
424
  updateRecursiveRefresh(jobId);
387
425
  async function updateJobId() {
388
- if (jobId !== job?.id) {
389
- $localModuleStates = {};
426
+ if (jobId !== job?.id || innerModules == undefined) {
427
+ localModuleStates = {};
390
428
  flowTimeline?.reset();
391
429
  timeout && clearTimeout(timeout);
392
- innerModules = [];
430
+ innerModules = undefined;
431
+ console.log('updateJobId', jobId);
393
432
  if (flowJobIds) {
394
433
  let modId = flowJobIds?.moduleId ?? '';
395
- let common = {
434
+ if (localDurationStatuses[modId] == undefined) {
435
+ localDurationStatuses[modId] = { byJob: {} };
436
+ }
437
+ let prefixed = buildSubflowKey(modId, prefix);
438
+ globalDurationStatuses.forEach((x) => {
439
+ if (x[prefixed] == undefined) {
440
+ x[prefixed] = { byJob: {} };
441
+ }
442
+ });
443
+ globalIterationBounds[prefixed] = {
396
444
  iteration_from: flowJobIds?.branchall ? 0 : Math.max(flowJobIds.flowJobs.length - 20, 0),
397
- iteration_total: $localDurationStatuses?.[modId]?.iteration_total ?? flowJobIds?.length
445
+ iteration_total: flowJobIds?.length
398
446
  };
399
- $localDurationStatuses[modId] = {
400
- ...($localDurationStatuses[modId] ?? { byJob: {} }),
401
- ...common
402
- };
403
- let prefixed = modId;
404
- globalDurationStatuses.forEach((x) => x.update((x) => {
405
- x[prefixed] = { ...(x[prefixed] ?? { byJob: {} }), ...common };
406
- return x;
407
- }));
408
447
  }
409
448
  else {
410
- updateRecursiveRefresh(jobId);
411
449
  recursiveRefresh = {};
412
- $localDurationStatuses = {};
450
+ localDurationStatuses = {};
451
+ updateRecursiveRefresh(jobId);
413
452
  }
414
453
  await loadJobInProgress();
415
454
  }
416
455
  }
417
- function getTopModuleStates() {
418
- return get(globalModuleStates?.[globalModuleStates?.length - 1]);
419
- }
420
- let forloop_selected = $state(getTopModuleStates()?.[flowJobIds?.moduleId ?? '']?.selectedForloop);
421
- let sub = undefined;
422
- let timeoutForloopSelectedSub = undefined;
423
- let timeoutForloopSelected = undefined;
424
- function onModuleIdChange() {
425
- clearTimeout(timeoutForloopSelectedSub);
426
- timeoutForloopSelectedSub = setTimeout(() => {
427
- sub?.();
428
- sub = globalModuleStates?.[globalModuleStates?.length - 1].subscribe((x) => {
429
- const newForloopSelected = x[flowJobIds?.moduleId ?? '']?.selectedForloop;
430
- if (newForloopSelected != forloop_selected) {
431
- clearTimeout(timeoutForloopSelected);
432
- timeoutForloopSelected = setTimeout(() => {
433
- forloop_selected = newForloopSelected;
434
- }, 200);
435
- }
436
- });
437
- }, 200);
438
- }
456
+ let forloop_selected = $state(getTopModuleStates?.[buildSubflowKey(flowJobIds?.moduleId ?? '', prefix)]?.selectedForloop);
439
457
  onDestroy(() => {
440
458
  destroyed = true;
441
459
  timeout && clearTimeout(timeout);
442
- sub?.();
460
+ // sub?.()
443
461
  });
444
462
  function isSuccess(arg) {
445
463
  if (arg == undefined) {
@@ -449,24 +467,23 @@ function isSuccess(arg) {
449
467
  return arg == true;
450
468
  }
451
469
  }
452
- function onJobsLoaded(mod, job, force) {
453
- if (mod.id && (mod.flow_jobs ?? []).length == 0) {
454
- if (!childFlow) {
455
- if ($flowStateStore?.[mod.id]) {
456
- $flowStateStore[mod.id] = {
457
- ...$flowStateStore[mod.id],
458
- previewResult: job['result'],
459
- previewArgs: job.args,
460
- previewJobId: job.id,
461
- previewWorkspaceId: job.workspace_id,
462
- previewSuccess: job['success']
463
- };
464
- }
470
+ function onJobsLoadedInner(mod, job, force) {
471
+ let id = mod.id;
472
+ if (id && ((mod.flow_jobs ?? []).length == 0 || force)) {
473
+ // console.debug('onJobsLoadedInner', id, job.id, force)
474
+ if (flowStateStore) {
475
+ flowStateStore[buildSubflowKey(id, prefix)] = {
476
+ ...(flowStateStore?.[buildSubflowKey(id, prefix)] ?? {}),
477
+ previewResult: job['result'],
478
+ previewArgs: job.args,
479
+ previewJobId: job.id,
480
+ previewSuccess: job['success']
481
+ };
465
482
  }
466
- initializeByJob(mod.id);
483
+ initializeByJob(id);
467
484
  let started_at = job.started_at ? new Date(job.started_at).getTime() : undefined;
468
485
  if (job.type == 'QueuedJob') {
469
- setModuleState(mod.id, {
486
+ setModuleState(id, {
470
487
  type: 'InProgress',
471
488
  job_id: job.id,
472
489
  logs: job.logs,
@@ -475,7 +492,7 @@ function onJobsLoaded(mod, job, force) {
475
492
  started_at,
476
493
  parent_module: mod['parent_module']
477
494
  }, force);
478
- setDurationStatusByJob(mod.id, job.id, {
495
+ setDurationStatusByJob(id, job.id, {
479
496
  created_at: job.created_at ? new Date(job.created_at).getTime() : undefined,
480
497
  started_at
481
498
  });
@@ -483,8 +500,8 @@ function onJobsLoaded(mod, job, force) {
483
500
  else {
484
501
  const parent_module = mod['parent_module'];
485
502
  // Delete existing failure node attached to the same parent module
486
- removeFailureNode(mod.id, parent_module);
487
- setModuleState(mod.id, {
503
+ removeFailureNode(id, parent_module);
504
+ setModuleState(id, {
488
505
  args: job.args,
489
506
  type: job['success'] ? 'Success' : 'Failure',
490
507
  logs: job.logs,
@@ -498,10 +515,11 @@ function onJobsLoaded(mod, job, force) {
498
515
  flow_jobs_success: mod.flow_jobs_success,
499
516
  iteration_total: mod.iterator?.itered?.length,
500
517
  retries: mod?.failed_retries?.length,
501
- skipped: mod.skipped
502
- // retries: $flowStateStore?.raw_flow
518
+ skipped: mod.skipped,
519
+ agent_actions: mod.agent_actions
520
+ // retries: flowStateStore?.raw_flow
503
521
  }, force);
504
- setDurationStatusByJob(mod.id, job.id, {
522
+ setDurationStatusByJob(id, job.id, {
505
523
  created_at: job.created_at ? new Date(job.created_at).getTime() : undefined,
506
524
  started_at,
507
525
  duration_ms: job['duration_ms']
@@ -511,11 +529,11 @@ function onJobsLoaded(mod, job, force) {
511
529
  }
512
530
  async function setIteration(j, id, clicked, modId, isForloop) {
513
531
  if (modId) {
514
- let globalState = globalModuleStates?.[globalModuleStates?.length - 1];
515
- let globalStateGet = globalState ? get(globalState) : undefined;
516
- let state = globalStateGet?.[modId];
532
+ let prefixedId = buildSubflowKey(modId, prefix);
533
+ let topModuleStates = getTopModuleStates;
534
+ let state = topModuleStates?.[prefixedId];
517
535
  if (clicked && state?.selectedForloop) {
518
- await globalRefreshes?.[modId]?.(true, state.selectedForloop);
536
+ await refreshGlobal?.(prefixedId, true, state.selectedForloop);
519
537
  }
520
538
  let manualOnce = state?.selectedForLoopSetManually;
521
539
  if (clicked ||
@@ -531,20 +549,19 @@ async function setIteration(j, id, clicked, modId, isForloop) {
531
549
  const selectedNotEqual = id != state?.selectedForloop ||
532
550
  j != state?.selectedForloopIndex ||
533
551
  setManually != state?.selectedForLoopSetManually;
552
+ // console.debug('setIteration', selectedNotEqual, state, topModuleStates)
534
553
  if (selectedNotEqual) {
535
- globalState?.update((topLevelModuleStates) => {
536
- topLevelModuleStates[modId] = {
554
+ if (topModuleStates) {
555
+ topModuleStates[prefixedId] = {
537
556
  type: 'WaitingForPriorSteps',
538
557
  args: {},
539
558
  ...newState
540
559
  };
541
- return topLevelModuleStates;
542
- // clicked && callGlobRefresh(modId, {index: j, job: id, selectedManually: setManually ?? false})
543
- });
560
+ }
544
561
  }
545
562
  }
546
563
  if (clicked) {
547
- await globalRefreshes?.[modId]?.(false, id);
564
+ await refreshGlobal?.(prefixedId, false, id);
548
565
  }
549
566
  }
550
567
  }
@@ -552,27 +569,31 @@ function innerJobLoaded(jobLoaded, j, clicked, force) {
552
569
  let modId = flowJobIds?.moduleId;
553
570
  if (modId) {
554
571
  setIteration(j, jobLoaded.id, clicked, modId, innerModule?.type == 'forloopflow' || innerModule?.type == 'whileloopflow');
555
- if ($flowStateStore && $flowStateStore?.[modId] == undefined) {
556
- $flowStateStore[modId] = {
557
- ...($flowStateStore[modId] ?? {}),
558
- previewResult: jobLoaded.args
559
- };
572
+ let prefixedId = buildSubflowKey(modId, prefix);
573
+ // if (flowStateStore) {
574
+ // flowStateStore[modId] = {
575
+ // ...((flowStateStore[modId] as object) ?? {}),
576
+ // previewResult: jobLoaded.args
577
+ // }
578
+ // }
579
+ if (flowStateStore && flowStateStore[prefixedId] == undefined) {
580
+ flowStateStore[prefixedId] = {};
560
581
  }
561
- if ($flowStateStore?.[modId]) {
562
- if (!childFlow) {
563
- if (!$flowStateStore[modId].previewResult ||
564
- !Array.isArray($flowStateStore[modId]?.previewResult)) {
565
- $flowStateStore[modId].previewResult = [];
566
- }
567
- $flowStateStore[modId].previewArgs = jobLoaded.args;
568
- }
569
- if (jobLoaded.type == 'QueuedJob') {
570
- jobResults[j] = 'Job in progress ...';
582
+ if (flowStateStore) {
583
+ if (!flowStateStore?.[prefixedId]?.previewResult ||
584
+ !Array.isArray(flowStateStore[prefixedId]?.previewResult)) {
585
+ flowStateStore[prefixedId].previewResult = [];
571
586
  }
572
- else if (jobLoaded.type == 'CompletedJob') {
573
- $flowStateStore[modId].previewResult[j] = jobLoaded.result;
574
- jobResults[j] = jobLoaded.result;
587
+ flowStateStore[prefixedId].previewArgs = jobLoaded.args;
588
+ }
589
+ if (jobLoaded.type == 'QueuedJob') {
590
+ jobResults[j] = 'Job in progress ...';
591
+ }
592
+ else if (jobLoaded.type == 'CompletedJob') {
593
+ if (flowStateStore?.[prefixedId]) {
594
+ flowStateStore[prefixedId].previewResult[j] = jobLoaded.result;
575
595
  }
596
+ jobResults[j] = jobLoaded.result;
576
597
  }
577
598
  let started_at = jobLoaded.started_at ? new Date(jobLoaded.started_at).getTime() : undefined;
578
599
  let created_at = jobLoaded.created_at ? new Date(jobLoaded.created_at).getTime() : undefined;
@@ -585,14 +606,14 @@ function innerJobLoaded(jobLoaded, j, clicked, force) {
585
606
  iteration_total: flowJobIds?.length,
586
607
  duration_ms: undefined
587
608
  };
588
- let currentIndex = getTopModuleStates()?.[modId]?.selectedForloopIndex == j;
609
+ let currentIndex = getTopModuleStates?.[prefixedId]?.selectedForloopIndex == j;
589
610
  if (currentIndex) {
590
611
  v.logs = jobLoaded.logs;
591
612
  v.args = jobLoaded.args;
592
613
  v.job_id = jobLoaded.id;
593
614
  }
594
615
  if (jobLoaded.type == 'QueuedJob') {
595
- if (started_at && $localModuleStates[modId]?.type != 'InProgress') {
616
+ if (started_at && localModuleStates[modId]?.type != 'InProgress') {
596
617
  v.type = 'InProgress';
597
618
  }
598
619
  }
@@ -623,47 +644,42 @@ function innerJobLoaded(jobLoaded, j, clicked, force) {
623
644
  id = innerModule?.modules?.[0]?.id;
624
645
  }
625
646
  if (id) {
626
- onJobsLoaded({ id }, jobLoaded);
647
+ onJobsLoadedInner({ id }, jobLoaded);
627
648
  }
628
649
  }
629
650
  }
630
651
  }
631
652
  let flowTimeline = $state();
632
- function loadPreviousIters(lenToAdd) {
633
- let r = $localDurationStatuses[flowJobIds?.moduleId ?? ''];
634
- if (r.iteration_from) {
635
- r.iteration_from -= lenToAdd;
636
- $localDurationStatuses = $localDurationStatuses;
637
- globalDurationStatuses.forEach((x) => x.update((x) => x));
653
+ function loadPreviousIters(innerKey, lenToAdd) {
654
+ let key = buildSubflowKey(innerKey, prefix);
655
+ if (globalIterationBounds[key]) {
656
+ globalIterationBounds[key].iteration_from =
657
+ (globalIterationBounds[key]?.iteration_from ?? 0) - lenToAdd;
638
658
  }
639
- jobResults = [
640
- ...[...new Array(lenToAdd).keys()].map((x) => 'not computed or loaded yet'),
641
- ...jobResults
642
- ];
643
659
  // updateSlicedListJobIds()
644
660
  }
645
661
  let stepDetail = $state(undefined);
646
662
  let storedListJobs = $state({});
663
+ let storedToolCallJobs = $state({});
664
+ let selectedToolCall = $state(undefined);
665
+ let toolCallIndicesToLoad = $state([]);
647
666
  let wrapperHeight = $state(0);
648
667
  function removeFailureNode(id, parent_module) {
649
668
  if (id?.startsWith('failure-') && parent_module) {
650
669
  ;
651
- [...globalModuleStates, localModuleStates].forEach((stateMapStore) => {
652
- stateMapStore.update((stateMap) => {
653
- if (id) {
654
- Object.keys(stateMap).forEach((key) => {
655
- if (stateMap[key]?.parent_module == parent_module) {
656
- delete stateMap[key];
657
- }
658
- });
659
- }
660
- return stateMap;
661
- });
670
+ [...globalModuleStates, localModuleStates].forEach((stateMap) => {
671
+ if (id) {
672
+ Object.keys(stateMap).forEach((key) => {
673
+ if (stateMap[key]?.parent_module == parent_module) {
674
+ delete stateMap[key];
675
+ }
676
+ });
677
+ }
662
678
  });
663
679
  }
664
680
  }
665
681
  function allModulesForTimeline(modules, expandedSubflows) {
666
- const ids = dfs(modules, (x) => x.id);
682
+ const ids = dfs(modules, (x) => x.id, { skipToolNodes: true });
667
683
  function rec(ids, prefix) {
668
684
  return ids.concat(ids.flatMap((id) => {
669
685
  let fms = expandedSubflows[id];
@@ -680,6 +696,45 @@ function allModulesForTimeline(modules, expandedSubflows) {
680
696
  return rec(ids, undefined);
681
697
  }
682
698
  let subflowsSize = $state(500);
699
+ function setParentModuleState(modId, state) {
700
+ ;
701
+ [localModuleStates, ...globalModuleStates].forEach((stateMap) => {
702
+ if (stateMap[modId]) {
703
+ stateMap[modId] = { ...stateMap[modId], ...state };
704
+ }
705
+ });
706
+ if (prefix) {
707
+ let prefixedId = buildSubflowKey(modId, prefix);
708
+ subflowParentsGlobalModuleStates.forEach((stateMap) => {
709
+ if (stateMap[prefixedId]) {
710
+ stateMap[prefixedId] = { ...stateMap[prefixedId], ...state };
711
+ }
712
+ });
713
+ }
714
+ }
715
+ async function onSelectedIteration(detail) {
716
+ let prefixedId = buildSubflowKey(detail.moduleId, prefix);
717
+ if (detail.manuallySet) {
718
+ let rootJobId = detail.id;
719
+ await tick();
720
+ let previousId = getTopModuleStates?.[prefixedId]?.selectedForloop;
721
+ if (previousId) {
722
+ await refreshGlobal?.(prefixedId, true, previousId);
723
+ }
724
+ setParentModuleState(detail.moduleId, {
725
+ selectedForloop: detail.id,
726
+ selectedForloopIndex: detail.index,
727
+ selectedForLoopSetManually: true
728
+ });
729
+ await tick();
730
+ await refreshGlobal?.(prefixedId, false, rootJobId);
731
+ }
732
+ else {
733
+ setParentModuleState(detail.moduleId, {
734
+ selectedForLoopSetManually: false
735
+ });
736
+ }
737
+ }
683
738
  $effect(() => {
684
739
  flowJobIds?.moduleId && untrack(() => onFlowModuleId());
685
740
  });
@@ -691,12 +746,24 @@ $effect(() => {
691
746
  });
692
747
  let isListJob = $derived(flowJobIds != undefined && Array.isArray(flowJobIds?.flowJobs));
693
748
  $effect(() => {
694
- flowJobIds?.moduleId && untrack(() => onModuleIdChange());
749
+ if (isSelectedBranch) {
750
+ let modId = flowJobIds?.moduleId;
751
+ if (modId) {
752
+ let selectedForloop = getTopModuleStates?.[buildSubflowKey(modId, prefix)]?.selectedForloop;
753
+ untrack(() => {
754
+ if (selectedForloop != forloop_selected) {
755
+ forloop_selected = selectedForloop;
756
+ }
757
+ });
758
+ }
759
+ }
695
760
  });
696
761
  let selected = $derived(isListJob ? 'sequence' : 'graph');
762
+ let animateLogsTab = $state(false);
763
+ let noLogs = $derived(graphTabOpen && !isNodeSelected);
697
764
  </script>
698
765
 
699
- <JobLoader workspaceOverride={workspaceId} noCode noLogs bind:this={jobLoader} />
766
+ <JobLoader workspaceOverride={workspaceId} {noLogs} noCode bind:this={jobLoader} />
700
767
  {#if notAnonynmous}
701
768
  <Alert type="error" title="Required Auth">
702
769
  As a non logged in user, you can only see jobs ran by anonymous users like you
@@ -709,16 +776,17 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
709
776
  <div class="h-8" />
710
777
  {/if} -->
711
778
  {#if isListJob}
712
- {@const sliceFrom = $localDurationStatuses[flowJobIds?.moduleId ?? '']?.iteration_from ?? 0}
779
+ {@const sliceFrom =
780
+ globalIterationBounds[buildSubflowKey(flowJobIds?.moduleId ?? '', prefix)]
781
+ ?.iteration_from ?? 0}
713
782
  {@const lenToAdd = Math.min(20, sliceFrom)}
714
-
715
783
  {#if (flowJobIds?.flowJobs.length ?? 0) > 20 && lenToAdd > 0}
716
784
  {@const allToAdd = (flowJobIds?.length ?? 0) - sliceFrom}
717
785
  <p class="text-tertiary italic text-xs">
718
786
  For performance reasons, only the last 20 items are shown by default <button
719
787
  class="text-primary underline ml-4"
720
788
  onclick={() => {
721
- loadPreviousIters(lenToAdd)
789
+ loadPreviousIters(flowJobIds?.moduleId ?? '', lenToAdd)
722
790
  }}
723
791
  >Load {lenToAdd} prior
724
792
  </button>
@@ -727,7 +795,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
727
795
  <button
728
796
  class="text-primary underline ml-4"
729
797
  onclick={() => {
730
- loadPreviousIters(allToAdd)
798
+ loadPreviousIters(flowJobIds?.moduleId ?? '', allToAdd)
731
799
  }}
732
800
  >Load {allToAdd} prior
733
801
  </button>
@@ -753,7 +821,6 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
753
821
  {isOwner}
754
822
  {hideFlowResult}
755
823
  {hideDownloadLogs}
756
- {localDurationStatuses}
757
824
  {innerModules}
758
825
  {suspendStatus}
759
826
  {hideJobId}
@@ -762,9 +829,15 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
762
829
  </div>
763
830
  {/if}
764
831
  {#if render}
765
- {#if innerModules.length > 0 && !isListJob}
832
+ {#if innerModules && innerModules.length > 0 && !isListJob}
766
833
  <Tabs class="mx-auto {wideResults ? '' : 'max-w-7xl'}" bind:selected>
767
834
  <Tab value="graph"><span class="font-semibold text-md">Graph</span></Tab>
835
+ <Tab
836
+ value="logs"
837
+ class={animateLogsTab
838
+ ? 'animate-pulse animate-duration-1000 bg-surface-inverse text-primary-inverse'
839
+ : ''}><span class="font-semibold">Logs</span></Tab
840
+ >
768
841
  <Tab value="sequence"><span class="font-semibold">Details</span></Tab>
769
842
  </Tabs>
770
843
  {:else}
@@ -773,7 +846,9 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
773
846
  {/if}
774
847
  <div class="{selected != 'sequence' ? 'hidden' : ''} max-w-7xl mx-auto">
775
848
  {#if isListJob}
776
- {@const sliceFrom = $localDurationStatuses[flowJobIds?.moduleId ?? '']?.iteration_from ?? 0}
849
+ {@const sliceFrom =
850
+ globalIterationBounds[buildSubflowKey(flowJobIds?.moduleId ?? '', prefix)]
851
+ ?.iteration_from ?? 0}
777
852
  <h3 class="text-md leading-6 font-bold text-tertiary border-b mb-4">
778
853
  Subflows ({flowJobIds?.flowJobs.length})
779
854
  </h3>
@@ -823,9 +898,10 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
823
898
  <!-- <LogId id={loopJobId} /> -->
824
899
  <div class="border p-6" class:hidden={forloop_selected != loopJobId}>
825
900
  <FlowStatusViewerInner
826
- {globalRefreshes}
827
- parentRecursiveRefresh={recursiveRefresh}
828
- {childFlow}
901
+ topModuleStates={getTopModuleStates}
902
+ {refreshGlobal}
903
+ isSelectedBranch={isSelectedBranch && forloopIsSelected}
904
+ updateRecursiveRefreshFn={updateRecursiveRefreshInner}
829
905
  job={storedListJobs[j]}
830
906
  initialJob={storedListJobs[j]}
831
907
  globalModuleStates={forloopIsSelected
@@ -837,6 +913,7 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
837
913
  ? subflowParentsGlobalModuleStates
838
914
  : []}
839
915
  {subflowParentsDurationStatuses}
916
+ {updateGlobalRefresh}
840
917
  render={forloop_selected == loopJobId && selected == 'sequence' && render}
841
918
  isForloopSelected={forloop_selected == loopJobId &&
842
919
  (innerModule?.type == 'forloopflow' || innerModule?.type == 'whileloopflow')}
@@ -844,25 +921,27 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
844
921
  (!!flowJobIds?.flowJobs.length && flowJobIds?.flowJobs.length > 20)}
845
922
  {workspaceId}
846
923
  jobId={loopJobId}
847
- on:jobsLoaded={(e) => {
848
- let { job, force } = e.detail
924
+ onJobsLoaded={({ job, force }) => {
849
925
  storedListJobs[j] = job
850
926
  innerJobLoaded(job, j, false, force)
851
927
  }}
852
928
  {onResultStreamUpdate}
929
+ graphTabOpen={selected == 'graph' && graphTabOpen}
930
+ isNodeSelected={forloop_selected == loopJobId}
931
+ {globalIterationBounds}
853
932
  />
854
933
  </div>
855
934
  {/if}
856
935
  {/each}
857
936
  </div>
858
- {:else if innerModules.length > 0 && (job.raw_flow?.modules.length ?? 0) > 0}
937
+ {:else if innerModules && innerModules.length > 0 && (job.raw_flow?.modules.length ?? 0) > 0}
859
938
  {@const hasPreprocessor = innerModules[0]?.id == 'preprocessor' ? 1 : 0}
860
939
  <ul class="w-full">
861
940
  <h3 class="text-md leading-6 font-bold text-primary border-b mb-4 py-2">
862
941
  Step-by-step
863
942
  </h3>
864
943
 
865
- {#each innerModules as mod, i}
944
+ {#each innerModules ?? [] as mod, i}
866
945
  {#if render}
867
946
  <div class="line w-8 h-10"></div>
868
947
  <h3 class="text-tertiary mb-2 w-full">
@@ -913,9 +992,11 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
913
992
  <!-- <LogId id={loopJobId} /> -->
914
993
  <div class="border p-6" class:hidden={retry_selected != failedRetry}>
915
994
  <FlowStatusViewerInner
916
- {globalRefreshes}
917
- parentRecursiveRefresh={recursiveRefresh}
918
- {childFlow}
995
+ topModuleStates={getTopModuleStates}
996
+ {refreshGlobal}
997
+ isSelectedBranch={isSelectedBranch && retry_selected == failedRetry}
998
+ {updateGlobalRefresh}
999
+ updateRecursiveRefreshFn={updateRecursiveRefreshInner}
919
1000
  globalModuleStates={[localModuleStates, ...globalModuleStates]}
920
1001
  globalDurationStatuses={[localDurationStatuses, ...globalDurationStatuses]}
921
1002
  {prefix}
@@ -926,6 +1007,9 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
926
1007
  {workspaceId}
927
1008
  jobId={failedRetry}
928
1009
  {onResultStreamUpdate}
1010
+ graphTabOpen={selected == 'graph' && graphTabOpen}
1011
+ isNodeSelected={retry_selected == failedRetry}
1012
+ {globalIterationBounds}
929
1013
  />
930
1014
  </div>
931
1015
  {/each}
@@ -933,10 +1017,14 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
933
1017
  {#if ['InProgress', 'Success', 'Failure'].includes(mod.type)}
934
1018
  {#if job.raw_flow?.modules[i]?.value.type == 'flow'}
935
1019
  <FlowStatusViewerInner
936
- {globalRefreshes}
937
- parentRecursiveRefresh={recursiveRefresh}
1020
+ topModuleStates={getTopModuleStates}
1021
+ {isSelectedBranch}
1022
+ {refreshGlobal}
1023
+ updateRecursiveRefreshFn={updateRecursiveRefreshInner}
938
1024
  globalModuleStates={[]}
1025
+ {updateGlobalRefresh}
939
1026
  globalDurationStatuses={[]}
1027
+ {globalIterationBounds}
940
1028
  prefix={buildPrefix(prefix, mod.id ?? '')}
941
1029
  subflowParentsGlobalModuleStates={[
942
1030
  localModuleStates,
@@ -953,27 +1041,29 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
953
1041
  jobId={mod.job ?? ''}
954
1042
  {reducedPolling}
955
1043
  isSubflow
956
- childFlow
957
- on:jobsLoaded={(e) => {
958
- let { force, job } = e.detail
959
- onJobsLoaded(mod, job, force)
1044
+ onJobsLoaded={({ job, force }) => {
1045
+ onJobsLoadedInner(mod, job, force)
960
1046
  }}
961
1047
  {onResultStreamUpdate}
1048
+ graphTabOpen={selected == 'graph' && graphTabOpen}
1049
+ isNodeSelected={false}
962
1050
  />
963
1051
  {:else if mod.flow_jobs?.length == 0 && mod.job == '00000000-0000-0000-0000-000000000000'}
964
1052
  <div class="text-secondary">no subflow (empty loop?)</div>
965
1053
  {:else}
966
1054
  <FlowStatusViewerInner
967
- {globalRefreshes}
968
- parentRecursiveRefresh={recursiveRefresh}
969
- {childFlow}
1055
+ topModuleStates={getTopModuleStates}
1056
+ {refreshGlobal}
1057
+ updateRecursiveRefreshFn={updateRecursiveRefreshInner}
970
1058
  globalModuleStates={[localModuleStates, ...globalModuleStates]}
971
1059
  globalDurationStatuses={[localDurationStatuses, ...globalDurationStatuses]}
972
1060
  render={selected == 'sequence' && render}
973
1061
  {workspaceId}
974
1062
  {prefix}
1063
+ {updateGlobalRefresh}
975
1064
  {subflowParentsGlobalModuleStates}
976
1065
  {subflowParentsDurationStatuses}
1066
+ {isSelectedBranch}
977
1067
  jobId={mod.job ?? ''}
978
1068
  {reducedPolling}
979
1069
  innerModule={mod.flow_jobs ? job.raw_flow?.modules[i]?.value : undefined}
@@ -986,17 +1076,93 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
986
1076
  branchall: job?.raw_flow?.modules?.[i]?.value?.type == 'branchall'
987
1077
  }
988
1078
  : undefined}
989
- on:jobsLoaded={(e) => {
990
- let { job, force } = e.detail
991
- onJobsLoaded(mod, job, force)
1079
+ onJobsLoaded={({ job, force }) => {
1080
+ onJobsLoadedInner(mod, job, force)
1081
+ }}
1082
+ loadExtraLogs={(logs) => {
1083
+ setModuleState(mod.id ?? '', {
1084
+ logs
1085
+ })
992
1086
  }}
993
1087
  {onResultStreamUpdate}
1088
+ graphTabOpen={selected == 'graph' && graphTabOpen}
1089
+ isNodeSelected={localModuleStates?.[selectedNode ?? '']?.job_id == mod.job}
1090
+ {globalIterationBounds}
994
1091
  />
1092
+ {#if mod.agent_actions && mod.agent_actions.length > 0}
1093
+ {#each mod.agent_actions as agentAction, j}
1094
+ {#if agentAction.type === 'tool_call' && mod.id}
1095
+ {@const toolCallId = getToolCallId(j, mod.id, agentAction.module_id)}
1096
+ {@const isSelected = selectedToolCall === j}
1097
+ <Button
1098
+ variant={isSelected ? 'contained' : 'border'}
1099
+ color={mod.agent_actions_success?.[j] === false
1100
+ ? 'red'
1101
+ : isSelected
1102
+ ? 'dark'
1103
+ : 'light'}
1104
+ btnClasses="w-full flex justify-start"
1105
+ on:click={async () => {
1106
+ if (selectedToolCall == j) {
1107
+ selectedToolCall = undefined
1108
+ } else {
1109
+ selectedToolCall = j
1110
+ }
1111
+ }}
1112
+ endIcon={{
1113
+ icon: ChevronDown,
1114
+ classes: isSelected ? '!rotate-180' : ''
1115
+ }}
1116
+ >
1117
+ <span class="truncate font-mono">
1118
+ Tool call: {agentAction.function_name}
1119
+ </span>
1120
+ </Button>
1121
+ {#if isSelected || storedToolCallJobs[j] || toolCallIndicesToLoad.includes(j)}
1122
+ <FlowStatusViewerInner
1123
+ topModuleStates={getTopModuleStates}
1124
+ {refreshGlobal}
1125
+ updateRecursiveRefreshFn={updateRecursiveRefreshInner}
1126
+ globalModuleStates={[localModuleStates, ...globalModuleStates]}
1127
+ globalDurationStatuses={[
1128
+ localDurationStatuses,
1129
+ ...globalDurationStatuses
1130
+ ]}
1131
+ render={selected == 'sequence' && render && isSelected}
1132
+ {workspaceId}
1133
+ {prefix}
1134
+ {updateGlobalRefresh}
1135
+ {subflowParentsGlobalModuleStates}
1136
+ {subflowParentsDurationStatuses}
1137
+ {isSelectedBranch}
1138
+ jobId={agentAction.job_id}
1139
+ job={storedToolCallJobs[j]}
1140
+ initialJob={storedToolCallJobs[j]}
1141
+ {reducedPolling}
1142
+ onJobsLoaded={({ job, force }) => {
1143
+ storedToolCallJobs[j] = job
1144
+ onJobsLoadedInner({ id: toolCallId } as FlowStatusModule, job, force)
1145
+ }}
1146
+ loadExtraLogs={(logs) => {
1147
+ setModuleState(toolCallId, {
1148
+ logs
1149
+ })
1150
+ }}
1151
+ {onResultStreamUpdate}
1152
+ graphTabOpen={selected == 'graph' && graphTabOpen}
1153
+ isNodeSelected={localModuleStates?.[toolCallId]?.job_id ==
1154
+ agentAction.job_id}
1155
+ {globalIterationBounds}
1156
+ />
1157
+ {/if}
1158
+ {/if}
1159
+ {/each}
1160
+ {/if}
995
1161
  {/if}
996
1162
  {:else}
997
1163
  <ModuleStatus
998
1164
  type={mod.type}
999
- scheduled_for={$localModuleStates?.[mod.id ?? '']?.scheduled_for}
1165
+ scheduled_for={localModuleStates?.[mod.id ?? '']?.scheduled_for}
1000
1166
  />
1001
1167
  {/if}
1002
1168
  </li>
@@ -1006,6 +1172,15 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1006
1172
  <div class="p-2 text-tertiary text-sm italic">Empty flow</div>
1007
1173
  {/if}
1008
1174
  </div>
1175
+ <div class="{selected != 'logs' ? 'hidden' : ''} mx-auto h-[800px]">
1176
+ <FlowLogViewerWrapper
1177
+ {job}
1178
+ {localModuleStates}
1179
+ {workspaceId}
1180
+ {render}
1181
+ {onSelectedIteration}
1182
+ />
1183
+ </div>
1009
1184
  </div>
1010
1185
  {#if render}
1011
1186
  {#if job.raw_flow && !isListJob}
@@ -1013,14 +1188,14 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1013
1188
  <div class="grid grid-cols-3 border h-full" bind:clientHeight={wrapperHeight}>
1014
1189
  <div class="col-span-2 bg-surface-secondary">
1015
1190
  <div class="flex flex-col">
1016
- {#each Object.values($retryStatus) as count}
1191
+ {#each Object.values(retryStatus?.val ?? {}) as count}
1017
1192
  {#if count}
1018
1193
  <span class="text-sm">
1019
1194
  Retry in progress, # of failed attempts: {count}
1020
1195
  </span>
1021
1196
  {/if}
1022
1197
  {/each}
1023
- {#each Object.values($suspendStatus) as count}
1198
+ {#each Object.values(suspendStatus?.val ?? {}) as count}
1024
1199
  {#if count.nb}
1025
1200
  <span class="text-sm">
1026
1201
  Flow suspended, waiting for {count.nb} events
@@ -1028,14 +1203,13 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1028
1203
  {/if}
1029
1204
  {/each}
1030
1205
  </div>
1031
-
1032
1206
  <FlowGraphV2
1033
1207
  {selectedId}
1034
1208
  triggerNode={true}
1035
1209
  download={!hideDownloadInGraph}
1036
1210
  minHeight={wrapperHeight}
1037
1211
  success={jobId != undefined && isSuccess(job?.['success'])}
1038
- flowModuleStates={$localModuleStates}
1212
+ flowModuleStates={localModuleStates}
1039
1213
  bind:expandedSubflows
1040
1214
  onSelect={(e) => {
1041
1215
  console.log('onSelect', e)
@@ -1050,42 +1224,26 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1050
1224
  selectedNode = 'end'
1051
1225
  stepDetail = 'end'
1052
1226
  } else {
1053
- const mod = dfs(job?.raw_flow?.modules ?? [], (m) => m).find((m) => m?.id === e)
1227
+ const id = e.startsWith(AI_TOOL_CALL_PREFIX) ? e.split('-').pop() : e
1228
+ const mod = dfs(job?.raw_flow?.modules ?? [], (m) => m).find(
1229
+ (m) => m?.id === id
1230
+ )
1054
1231
  stepDetail = mod
1055
1232
  selectedNode = e
1233
+ if (e.startsWith(AI_TOOL_CALL_PREFIX)) {
1234
+ const [_prefix, _agentModuleId, j, _toolModuleId] = e.split('-')
1235
+ const jIdx = Number(j)
1236
+ if (!toolCallIndicesToLoad.includes(jIdx)) {
1237
+ toolCallIndicesToLoad.push(jIdx)
1238
+ }
1239
+ }
1056
1240
  }
1057
1241
  } else {
1058
1242
  stepDetail = e
1059
1243
  selectedNode = e.id
1060
1244
  }
1061
1245
  }}
1062
- onSelectedIteration={async (detail) => {
1063
- if (detail.manuallySet) {
1064
- let rootJobId = detail.id
1065
- await tick()
1066
-
1067
- let previousId = $localModuleStates[detail.moduleId]?.selectedForloop
1068
- if (previousId) {
1069
- await globalRefreshes?.[detail.moduleId]?.(true, previousId)
1070
- }
1071
-
1072
- $localModuleStates[detail.moduleId] = {
1073
- ...$localModuleStates[detail.moduleId],
1074
- selectedForloop: detail.id,
1075
- selectedForloopIndex: detail.index,
1076
- selectedForLoopSetManually: true
1077
- }
1078
-
1079
- await tick()
1080
-
1081
- await globalRefreshes?.[detail.moduleId]?.(false, rootJobId)
1082
- } else {
1083
- $localModuleStates[detail.moduleId] = {
1084
- ...$localModuleStates[detail.moduleId],
1085
- selectedForLoopSetManually: false
1086
- }
1087
- }
1088
- }}
1246
+ {onSelectedIteration}
1089
1247
  earlyStop={job.raw_flow?.skip_expr !== undefined}
1090
1248
  cache={job.raw_flow?.cache_ttl !== undefined}
1091
1249
  modules={job.raw_flow?.modules ?? []}
@@ -1121,13 +1279,21 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1121
1279
  job?.raw_flow?.modules ?? [],
1122
1280
  expandedSubflows ?? {}
1123
1281
  )}
1282
+ buildSubflowKey={(key) => buildSubflowKey(key, prefix)}
1283
+ {globalIterationBounds}
1124
1284
  durationStatuses={localDurationStatuses}
1285
+ decreaseIterationFrom={(key, amount) => {
1286
+ loadPreviousIters(key, amount)
1287
+ }}
1125
1288
  />
1126
1289
  {:else if rightColumnSelect == 'node_status'}
1127
1290
  <div class="pt-2 grow flex flex-col">
1128
- {#if selectedNode}
1129
- {@const node = $localModuleStates[selectedNode]}
1130
-
1291
+ {#if selectedNode?.startsWith(AI_TOOL_MESSAGE_PREFIX)}
1292
+ <div class="pt-2 px-4 pb-4">
1293
+ <Alert type="info" title="Message output is available on the AI agent node" />
1294
+ </div>
1295
+ {:else if selectedNode}
1296
+ {@const node = localModuleStates[selectedNode]}
1131
1297
  {#if selectedNode == 'end'}
1132
1298
  <FlowJobResult
1133
1299
  tagLabel={customUi?.tagLabel}
@@ -1140,7 +1306,6 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1140
1306
  col
1141
1307
  result={job['result']}
1142
1308
  logs={job.logs ?? ''}
1143
- durationStates={localDurationStatuses}
1144
1309
  downloadLogs={!hideDownloadLogs}
1145
1310
  />
1146
1311
  {:else if selectedNode == 'start'}
@@ -1156,6 +1321,10 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1156
1321
  <p class="p-2 text-secondary">No arguments</p>
1157
1322
  {/if}
1158
1323
  {:else if node}
1324
+ {@const module =
1325
+ stepDetail && typeof stepDetail !== 'string' ? stepDetail : undefined}
1326
+ {@const agentTools =
1327
+ module && module.value.type === 'aiagent' ? module.value.tools : undefined}
1159
1328
  {#if node.flow_jobs_results}
1160
1329
  <span class="pl-1 text-tertiary"
1161
1330
  >Result of step as collection of all subflows</span
@@ -1218,8 +1387,26 @@ let selected = $derived(isListJob ? 'sequence' : 'graph');
1218
1387
  result={node.result}
1219
1388
  tag={node.tag}
1220
1389
  logs={node.logs}
1221
- durationStates={localDurationStatuses}
1222
1390
  downloadLogs={!hideDownloadLogs}
1391
+ aiAgentStatus={agentTools &&
1392
+ node.job_id &&
1393
+ (node.type === 'Success' || node.type === 'Failure')
1394
+ ? {
1395
+ tools: agentTools,
1396
+ agentJob: {
1397
+ id: node.job_id,
1398
+ result: node.result,
1399
+ logs: node.logs,
1400
+ args: node.args,
1401
+ success: node.type === 'Success',
1402
+ type: 'CompletedJob'
1403
+ },
1404
+ storedToolCallJobs,
1405
+ onToolJobLoaded: (job, idx) => {
1406
+ storedToolCallJobs[idx] = job
1407
+ }
1408
+ }
1409
+ : undefined}
1223
1410
  />
1224
1411
  {:else}
1225
1412
  <p class="p-2 text-tertiary italic"