windmill-components 1.531.1 → 1.537.1

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 (153) hide show
  1. package/package/components/ArgInput.svelte +69 -19
  2. package/package/components/Auth0Setting.svelte +8 -3
  3. package/package/components/Dev.svelte +5 -4
  4. package/package/components/DiffDrawer.svelte +2 -2
  5. package/package/components/DiffEditor.svelte +34 -37
  6. package/package/components/DiffEditor.svelte.d.ts +23 -39
  7. package/package/components/EditableSchemaForm.svelte +67 -67
  8. package/package/components/EditableSchemaForm.svelte.d.ts +3 -3
  9. package/package/components/Editor.svelte +32 -11
  10. package/package/components/Editor.svelte.d.ts +6 -0
  11. package/package/components/EditorBar.svelte +2 -2
  12. package/package/components/EditorBar.svelte.d.ts +1 -0
  13. package/package/components/FieldHeader.svelte +1 -1
  14. package/package/components/FlowBuilder.svelte +7 -4
  15. package/package/components/FlowPreviewContent.svelte +3 -3
  16. package/package/components/FlowStatusViewer.svelte +28 -0
  17. package/package/components/FlowStatusViewerInner.svelte +72 -20
  18. package/package/components/FlowStatusViewerInner.svelte.d.ts +7 -0
  19. package/package/components/ModulePreview.svelte +2 -1
  20. package/package/components/ModulePreview.svelte.d.ts +1 -0
  21. package/package/components/ModulePreviewForm.svelte +72 -65
  22. package/package/components/ModulePreviewResultViewer.svelte +13 -18
  23. package/package/components/ModuleTest.svelte +10 -6
  24. package/package/components/ModuleTest.svelte.d.ts +1 -0
  25. package/package/components/OktaSetting.svelte +8 -3
  26. package/package/components/Portal.svelte +11 -7
  27. package/package/components/Portal.svelte.d.ts +19 -39
  28. package/package/components/ResourceEditor.svelte +4 -0
  29. package/package/components/RunForm.svelte +2 -2
  30. package/package/components/RunForm.svelte.d.ts +1 -1
  31. package/package/components/RunFormAdvancedPopup.svelte +13 -1
  32. package/package/components/SchemaForm.svelte +1 -2
  33. package/package/components/ScriptBuilder.svelte +1 -1
  34. package/package/components/ScriptEditor.svelte +22 -7
  35. package/package/components/SimpleEditor.svelte +0 -1
  36. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  37. package/package/components/apps/components/layout/AppModal.svelte +2 -2
  38. package/package/components/apps/editor/component/ComponentNavigation.svelte +3 -2
  39. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +1 -1
  40. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +0 -1
  41. package/package/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +3 -1
  42. package/package/components/apps/editor/settingsPanel/GridCondition.svelte +3 -1
  43. package/package/components/apps/editor/settingsPanel/GridNavbar.svelte +3 -1
  44. package/package/components/apps/editor/settingsPanel/GridTab.svelte +3 -1
  45. package/package/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte +55 -53
  46. package/package/components/apps/editor/settingsPanel/TableActions.svelte +3 -1
  47. package/package/components/common/button/model.d.ts +1 -1
  48. package/package/components/common/drawer/Disposable.svelte +51 -30
  49. package/package/components/common/drawer/Disposable.svelte.d.ts +12 -44
  50. package/package/components/common/drawer/Drawer.svelte +15 -11
  51. package/package/components/copilot/FlowInlineScriptAIButton.svelte +4 -2
  52. package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +4 -1
  53. package/package/components/copilot/MetadataGen.svelte +14 -3
  54. package/package/components/copilot/autocomplete/Autocompletor.js +0 -2
  55. package/package/components/copilot/chat/AIChat.svelte +2 -4
  56. package/package/components/copilot/chat/AIChatInput.svelte +3 -3
  57. package/package/components/copilot/chat/AIChatManager.svelte.js +24 -12
  58. package/package/components/copilot/chat/AvailableContextList.svelte +243 -26
  59. package/package/components/copilot/chat/AvailableContextList.svelte.d.ts +2 -1
  60. package/package/components/copilot/chat/ContextElementBadge.svelte +31 -15
  61. package/package/components/copilot/chat/ContextElementBadge.svelte.d.ts +5 -20
  62. package/package/components/copilot/chat/ContextManager.svelte.d.ts +15 -2
  63. package/package/components/copilot/chat/ContextManager.svelte.js +134 -24
  64. package/package/components/copilot/chat/ContextTextarea.svelte +22 -49
  65. package/package/components/copilot/chat/ToolContentDisplay.svelte +10 -1
  66. package/package/components/copilot/chat/ToolExecutionDisplay.svelte +3 -3
  67. package/package/components/copilot/chat/context.d.ts +19 -1
  68. package/package/components/copilot/chat/context.js +1 -0
  69. package/package/components/copilot/chat/flow/FlowAIChat.svelte +109 -7
  70. package/package/components/copilot/chat/flow/core.d.ts +13 -1
  71. package/package/components/copilot/chat/flow/core.js +171 -19
  72. package/package/components/copilot/chat/flow/uiIntents.d.ts +8 -0
  73. package/package/components/copilot/chat/flow/uiIntents.js +5 -0
  74. package/package/components/copilot/chat/flow/useUiIntent.d.ts +5 -0
  75. package/package/components/copilot/chat/flow/useUiIntent.js +12 -0
  76. package/package/components/copilot/chat/monaco-adapter.d.ts +22 -4
  77. package/package/components/copilot/chat/monaco-adapter.js +55 -16
  78. package/package/components/copilot/chat/script/core.d.ts +2 -2
  79. package/package/components/copilot/chat/script/core.js +54 -124
  80. package/package/components/copilot/chat/shared.d.ts +14 -2
  81. package/package/components/copilot/chat/shared.js +170 -7
  82. package/package/components/copilot/lib.js +12 -7
  83. package/package/components/copilot/shared.d.ts +1 -1
  84. package/package/components/copilot/shared.js +16 -10
  85. package/package/components/flows/FlowEditor.svelte +15 -1
  86. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  87. package/package/components/flows/FlowModuleIcon.svelte +39 -0
  88. package/package/components/flows/FlowModuleIcon.svelte.d.ts +10 -0
  89. package/package/components/flows/common/FlowCardHeader.svelte +4 -1
  90. package/package/components/flows/content/FlowBranchesAllWrapper.svelte +6 -0
  91. package/package/components/flows/content/FlowBranchesOneWrapper.svelte +6 -0
  92. package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
  93. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
  94. package/package/components/flows/content/FlowInput.svelte +31 -34
  95. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
  96. package/package/components/flows/content/FlowLoop.svelte +7 -0
  97. package/package/components/flows/content/FlowModuleComponent.svelte +39 -44
  98. package/package/components/flows/content/FlowModuleScript.svelte +1 -1
  99. package/package/components/flows/content/FlowModuleSuspend.svelte +16 -18
  100. package/package/components/flows/content/FlowWhileLoop.svelte +6 -0
  101. package/package/components/flows/content/ScriptEditorDrawer.svelte +9 -11
  102. package/package/components/flows/dfs.d.ts +1 -1
  103. package/package/components/flows/dfs.js +6 -6
  104. package/package/components/flows/flowInfers.js +7 -7
  105. package/package/components/flows/flowStateUtils.svelte.js +1 -2
  106. package/package/components/flows/map/FlowModuleSchemaItem.svelte +12 -26
  107. package/package/components/flows/map/MapItem.svelte +12 -39
  108. package/package/components/flows/map/VirtualItem.svelte +1 -1
  109. package/package/components/flows/pickers/TopLevelNode.svelte +1 -1
  110. package/package/components/flows/propPicker/InputPickerInner.svelte +5 -5
  111. package/package/components/flows/propPicker/OutputPickerInner.svelte +143 -118
  112. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +7 -16
  113. package/package/components/flows/{testSteps.svelte.d.ts → stepsInputArgs.svelte.d.ts} +2 -1
  114. package/package/components/flows/{testSteps.svelte.js → stepsInputArgs.svelte.js} +15 -3
  115. package/package/components/flows/types.d.ts +16 -3
  116. package/package/components/flows/utils.js +3 -0
  117. package/package/components/graph/FlowGraphV2.svelte +1 -1
  118. package/package/components/graph/renderers/nodes/AIToolNode.svelte +4 -4
  119. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +71 -54
  120. package/package/components/propertyPicker/ObjectViewer.svelte +11 -3
  121. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +1 -1
  122. package/package/components/schema/AddPropertyV2.svelte +2 -7
  123. package/package/components/schema/AddPropertyV2.svelte.d.ts +3 -20
  124. package/package/components/schema/EditableSchemaDrawer.svelte +109 -115
  125. package/package/components/schema/EditableSchemaDrawer.svelte.d.ts +2 -1
  126. package/package/components/schema/EditableSchemaSdkWrapper.svelte +16 -3
  127. package/package/components/schema/EditableSchemaSdkWrapper.svelte.d.ts +4 -1
  128. package/package/components/schema/EditableSchemaWrapper.svelte +3 -10
  129. package/package/components/schema/FlowPropertyEditor.svelte +83 -57
  130. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +1 -1
  131. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  132. package/package/components/schema/SchemaFormDND.svelte +11 -10
  133. package/package/components/schema/SchemaFormDND.svelte.d.ts +3 -2
  134. package/package/components/schema/editable_schema_wrapper.d.ts +0 -3
  135. package/package/components/schema/jsonSchemaResource.svelte.d.ts +2 -0
  136. package/package/components/schema/jsonSchemaResource.svelte.js +40 -0
  137. package/package/components/settings/PremiumInfo.svelte +7 -2
  138. package/package/components/triggers/CaptureWrapper.svelte +2 -13
  139. package/package/components/triggers/CaptureWrapper.svelte.d.ts +1 -1
  140. package/package/components/triggers/TriggersWrapper.svelte +1 -0
  141. package/package/components/triggers/http/RouteEditorInner.svelte +1 -1
  142. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +23 -20
  143. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte +15 -27
  144. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte.d.ts +7 -5
  145. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +16 -16
  146. package/package/hubPaths.json +3 -1
  147. package/package/script_helpers.d.ts +2 -2
  148. package/package/script_helpers.js +2 -0
  149. package/package/stores.d.ts +1 -0
  150. package/package/stores.js +8 -1
  151. package/package/utils.d.ts +1 -1
  152. package/package.json +14 -14
  153. package/package/components/ModulePreviewResultViewer.svelte.d.ts +0 -28
@@ -16,6 +16,7 @@ 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 { dfs as dfsPreviousResults } from './flows/previousResults';
19
20
  import Alert from './common/alert/Alert.svelte';
20
21
  import FlowGraphViewerStep from './FlowGraphViewerStep.svelte';
21
22
  import FlowGraphV2 from './graph/FlowGraphV2.svelte';
@@ -28,7 +29,7 @@ import JobLoader from './JobLoader.svelte';
28
29
  import { writable } from 'svelte/store';
29
30
  import { AI_TOOL_CALL_PREFIX, AI_TOOL_MESSAGE_PREFIX, getToolCallId } from './graph/renderers/nodes/AIToolNode.svelte';
30
31
  let { flowStateStore, retryStatus, suspendStatus, hideDownloadInGraph, hideTimeline, hideNodeDefinition, hideDownloadLogs, hideJobId } = getContext('FlowStatusViewer');
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 { 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
33
  let getTopModuleStates = $derived(topModuleStates ?? localModuleStates);
33
34
  let resultStreams = $state({});
34
35
  if (onResultStreamUpdate == undefined) {
@@ -660,9 +661,7 @@ function loadPreviousIters(innerKey, lenToAdd) {
660
661
  }
661
662
  let stepDetail = $state(undefined);
662
663
  let storedListJobs = $state({});
663
- let storedToolCallJobs = $state({});
664
664
  let selectedToolCall = $state(undefined);
665
- let toolCallIndicesToLoad = $state([]);
666
665
  let wrapperHeight = $state(0);
667
666
  function removeFailureNode(id, parent_module) {
668
667
  if (id?.startsWith('failure-') && parent_module) {
@@ -689,7 +688,7 @@ function allModulesForTimeline(modules, expandedSubflows) {
689
688
  }
690
689
  let nprefix = buildPrefix(prefix, oid);
691
690
  return fms
692
- ? rec(dfs(fms, (x) => x.id.startsWith('subflow:') ? x.id : buildSubflowKey(x.id, nprefix)), nprefix)
691
+ ? rec(dfs(fms, (x) => (x.id.startsWith('subflow:') ? x.id : buildSubflowKey(x.id, nprefix)), { skipToolNodes: true }), nprefix)
693
692
  : [];
694
693
  }));
695
694
  }
@@ -734,6 +733,11 @@ async function onSelectedIteration(detail) {
734
733
  selectedForLoopSetManually: false
735
734
  });
736
735
  }
736
+ if (selectedNode?.startsWith(AI_TOOL_CALL_PREFIX)) {
737
+ const [, agentModuleId, toolCallIndex, _] = selectedNode.split('-');
738
+ const parentLoopsPrefix = getParentLoopsPrefix(agentModuleId);
739
+ toolCallStore?.addToolCallToLoad(parentLoopsPrefix + agentModuleId + '-' + toolCallIndex);
740
+ }
737
741
  }
738
742
  $effect(() => {
739
743
  flowJobIds?.moduleId && untrack(() => onFlowModuleId());
@@ -761,6 +765,27 @@ $effect(() => {
761
765
  let selected = $derived(isListJob ? 'sequence' : 'graph');
762
766
  let animateLogsTab = $state(false);
763
767
  let noLogs = $derived(graphTabOpen && !isNodeSelected);
768
+ /**
769
+ * Returns a string like "forloopmodid1-{iter1}-forloopmodid2-{iter2}-forloopmodid3-{iter3}-"
770
+ * that can be used to prefix tool call store keys for nested tool calls.
771
+ */
772
+ function getParentLoopsPrefix(modId) {
773
+ if (job?.raw_flow) {
774
+ const indices = [];
775
+ const parents = dfsPreviousResults(modId, { value: job?.raw_flow, summary: '' }, true);
776
+ for (const parent of parents) {
777
+ if (parent.value.type === 'forloopflow' || parent.value.type === 'whileloopflow') {
778
+ const state = localModuleStates[parent.id];
779
+ if (state?.selectedForloopIndex !== undefined) {
780
+ indices.push(parent.id + '-' + state.selectedForloopIndex.toString());
781
+ }
782
+ }
783
+ }
784
+ indices.reverse();
785
+ return indices.length > 0 ? indices.join('-') + '-' : '';
786
+ }
787
+ return '';
788
+ }
764
789
  </script>
765
790
 
766
791
  <JobLoader workspaceOverride={workspaceId} {noLogs} noCode bind:this={jobLoader} />
@@ -895,6 +920,10 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
895
920
  {@const forloopIsSelected =
896
921
  forloop_selected == loopJobId ||
897
922
  (innerModule?.type != 'forloopflow' && innerModule?.type != 'whileloopflow')}
923
+ {@const forLoopStoreKeyPrefix =
924
+ innerModule?.type == 'forloopflow' || innerModule?.type == 'whileloopflow'
925
+ ? (flowJobIds?.moduleId ?? '') + '-' + j + '-'
926
+ : ''}
898
927
  <!-- <LogId id={loopJobId} /> -->
899
928
  <div class="border p-6" class:hidden={forloop_selected != loopJobId}>
900
929
  <FlowStatusViewerInner
@@ -929,6 +958,18 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
929
958
  graphTabOpen={selected == 'graph' && graphTabOpen}
930
959
  isNodeSelected={forloop_selected == loopJobId}
931
960
  {globalIterationBounds}
961
+ toolCallStore={{
962
+ getStoredToolCallJob: (storeKey: string) =>
963
+ toolCallStore?.getStoredToolCallJob(forLoopStoreKeyPrefix + storeKey),
964
+ setStoredToolCallJob: (storeKey: string, job: Job) =>
965
+ toolCallStore?.setStoredToolCallJob(forLoopStoreKeyPrefix + storeKey, job),
966
+ getLocalToolCallJobs: (prefix: string) =>
967
+ toolCallStore?.getLocalToolCallJobs(forLoopStoreKeyPrefix + prefix) ?? {},
968
+ addToolCallToLoad: (storeKey: string) =>
969
+ toolCallStore?.addToolCallToLoad(forLoopStoreKeyPrefix + storeKey),
970
+ isToolCallToBeLoaded: (storeKey: string) =>
971
+ toolCallStore?.isToolCallToBeLoaded(forLoopStoreKeyPrefix + storeKey) ?? false
972
+ }}
932
973
  />
933
974
  </div>
934
975
  {/if}
@@ -1088,12 +1129,17 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1088
1129
  graphTabOpen={selected == 'graph' && graphTabOpen}
1089
1130
  isNodeSelected={localModuleStates?.[selectedNode ?? '']?.job_id == mod.job}
1090
1131
  {globalIterationBounds}
1132
+ {toolCallStore}
1091
1133
  />
1092
- {#if mod.agent_actions && mod.agent_actions.length > 0}
1134
+ {#if mod.agent_actions && mod.agent_actions.length > 0 && mod.id}
1135
+ {@const storeKeyPrefix = getParentLoopsPrefix(mod.id)}
1093
1136
  {#each mod.agent_actions as agentAction, j}
1094
- {#if agentAction.type === 'tool_call' && mod.id}
1137
+ {#if agentAction.type === 'tool_call'}
1095
1138
  {@const toolCallId = getToolCallId(j, mod.id, agentAction.module_id)}
1096
- {@const isSelected = selectedToolCall === j}
1139
+ {@const localToolCallKey = mod.id + '-' + j}
1140
+ {@const storeKey = storeKeyPrefix + localToolCallKey}
1141
+ {@const storedToolCallJob = toolCallStore?.getStoredToolCallJob(storeKey)}
1142
+ {@const isSelected = localToolCallKey === selectedToolCall}
1097
1143
  <Button
1098
1144
  variant={isSelected ? 'contained' : 'border'}
1099
1145
  color={mod.agent_actions_success?.[j] === false
@@ -1103,10 +1149,10 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1103
1149
  : 'light'}
1104
1150
  btnClasses="w-full flex justify-start"
1105
1151
  on:click={async () => {
1106
- if (selectedToolCall == j) {
1152
+ if (isSelected) {
1107
1153
  selectedToolCall = undefined
1108
1154
  } else {
1109
- selectedToolCall = j
1155
+ selectedToolCall = localToolCallKey
1110
1156
  }
1111
1157
  }}
1112
1158
  endIcon={{
@@ -1118,7 +1164,7 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1118
1164
  Tool call: {agentAction.function_name}
1119
1165
  </span>
1120
1166
  </Button>
1121
- {#if isSelected || storedToolCallJobs[j] || toolCallIndicesToLoad.includes(j)}
1167
+ {#if isSelected || storedToolCallJob || toolCallStore?.isToolCallToBeLoaded(storeKey)}
1122
1168
  <FlowStatusViewerInner
1123
1169
  topModuleStates={getTopModuleStates}
1124
1170
  {refreshGlobal}
@@ -1136,11 +1182,11 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1136
1182
  {subflowParentsDurationStatuses}
1137
1183
  {isSelectedBranch}
1138
1184
  jobId={agentAction.job_id}
1139
- job={storedToolCallJobs[j]}
1140
- initialJob={storedToolCallJobs[j]}
1185
+ job={storedToolCallJob}
1186
+ initialJob={storedToolCallJob}
1141
1187
  {reducedPolling}
1142
1188
  onJobsLoaded={({ job, force }) => {
1143
- storedToolCallJobs[j] = job
1189
+ toolCallStore?.setStoredToolCallJob(storeKey, job)
1144
1190
  onJobsLoadedInner({ id: toolCallId } as FlowStatusModule, job, force)
1145
1191
  }}
1146
1192
  loadExtraLogs={(logs) => {
@@ -1231,11 +1277,11 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1231
1277
  stepDetail = mod
1232
1278
  selectedNode = e
1233
1279
  if (e.startsWith(AI_TOOL_CALL_PREFIX)) {
1234
- const [_prefix, _agentModuleId, j, _toolModuleId] = e.split('-')
1280
+ const [_prefix, agentModuleId, j, _toolModuleId] = e.split('-')
1281
+ const parentLoopsPrefix = getParentLoopsPrefix(agentModuleId)
1235
1282
  const jIdx = Number(j)
1236
- if (!toolCallIndicesToLoad.includes(jIdx)) {
1237
- toolCallIndicesToLoad.push(jIdx)
1238
- }
1283
+ const storeKey = parentLoopsPrefix + agentModuleId + '-' + jIdx
1284
+ toolCallStore?.addToolCallToLoad(storeKey)
1239
1285
  }
1240
1286
  }
1241
1287
  } else {
@@ -1325,6 +1371,7 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1325
1371
  stepDetail && typeof stepDetail !== 'string' ? stepDetail : undefined}
1326
1372
  {@const agentTools =
1327
1373
  module && module.value.type === 'aiagent' ? module.value.tools : undefined}
1374
+ {@const parentLoopsPrefix = getParentLoopsPrefix(module?.id ?? '')}
1328
1375
  {#if node.flow_jobs_results}
1329
1376
  <span class="pl-1 text-tertiary"
1330
1377
  >Result of step as collection of all subflows</span
@@ -1389,7 +1436,7 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1389
1436
  logs={node.logs}
1390
1437
  downloadLogs={!hideDownloadLogs}
1391
1438
  aiAgentStatus={agentTools &&
1392
- node.job_id &&
1439
+ node?.job_id &&
1393
1440
  (node.type === 'Success' || node.type === 'Failure')
1394
1441
  ? {
1395
1442
  tools: agentTools,
@@ -1401,9 +1448,14 @@ let noLogs = $derived(graphTabOpen && !isNodeSelected);
1401
1448
  success: node.type === 'Success',
1402
1449
  type: 'CompletedJob'
1403
1450
  },
1404
- storedToolCallJobs,
1451
+ storedToolCallJobs: module
1452
+ ? toolCallStore?.getLocalToolCallJobs(parentLoopsPrefix)
1453
+ : undefined,
1405
1454
  onToolJobLoaded: (job, idx) => {
1406
- storedToolCallJobs[idx] = job
1455
+ if (module) {
1456
+ const storeKey = parentLoopsPrefix + module.id + '-' + idx
1457
+ toolCallStore?.setStoredToolCallJob(storeKey, job)
1458
+ }
1407
1459
  }
1408
1460
  }
1409
1461
  : undefined}
@@ -57,6 +57,13 @@ interface Props {
57
57
  onDone?: ({ job }: {
58
58
  job: CompletedJob;
59
59
  }) => void;
60
+ toolCallStore?: {
61
+ getStoredToolCallJob: (storeKey: string) => Job | undefined;
62
+ setStoredToolCallJob: (storeKey: string, job: Job) => void;
63
+ getLocalToolCallJobs: (prefix: string) => Record<number, Job>;
64
+ isToolCallToBeLoaded: (storeKey: string) => boolean;
65
+ addToolCallToLoad: (storeKey: string) => void;
66
+ };
60
67
  }
61
68
  declare const FlowStatusViewerInner: import("svelte").Component<Props, {}, "job" | "localModuleStates" | "selectedNode" | "rightColumnSelect" | "localDurationStatuses">;
62
69
  type FlowStatusViewerInner = ReturnType<typeof FlowStatusViewerInner>;
@@ -4,7 +4,7 @@ import Button from './common/button/Button.svelte';
4
4
  import ModulePreviewForm from './ModulePreviewForm.svelte';
5
5
  import ModuleTest from './ModuleTest.svelte';
6
6
  import { getContext } from 'svelte';
7
- let { mod, schema, pickableProperties, testJob = $bindable(undefined), testIsLoading = $bindable(false), noEditor = false, scriptProgress = $bindable(undefined), focusArg = undefined } = $props();
7
+ let { mod, schema, pickableProperties, testJob = $bindable(undefined), testIsLoading = $bindable(false), noEditor = false, scriptProgress = $bindable(undefined), focusArg = undefined, onJobDone } = $props();
8
8
  const { flowStore } = getContext('FlowEditorContext');
9
9
  let moduleTest = $state();
10
10
  export function runTestWithStepArgs() {
@@ -19,6 +19,7 @@ export function runTestWithStepArgs() {
19
19
  bind:testIsLoading
20
20
  bind:scriptProgress
21
21
  bind:this={moduleTest}
22
+ {onJobDone}
22
23
  />
23
24
 
24
25
  <div class="p-4">
@@ -12,6 +12,7 @@ interface Props {
12
12
  noEditor?: boolean;
13
13
  scriptProgress?: any;
14
14
  focusArg?: string;
15
+ onJobDone?: () => void;
15
16
  }
16
17
  declare const ModulePreview: import("svelte").Component<Props, {
17
18
  runTestWithStepArgs: () => void;
@@ -1,13 +1,13 @@
1
- <script lang="ts">import { allTrue, sendUserToast } from '../utils';
1
+ <script lang="ts">import { allTrue } from '../utils';
2
2
  import { RefreshCw } from 'lucide-svelte';
3
3
  import ArgInput from './ArgInput.svelte';
4
4
  import { Button } from './common';
5
- import { getContext, onMount, untrack } from 'svelte';
5
+ import { getContext, untrack } from 'svelte';
6
6
  import { evalValue } from './flows/utils';
7
7
  import { getResourceTypes } from './resourceTypesStore';
8
8
  import { twMerge } from 'tailwind-merge';
9
9
  let { schema, mod, pickableProperties, isValid = $bindable(true), autofocus = false, focusArg = undefined } = $props();
10
- const { testSteps, flowStateStore, flowStore, previewArgs } = getContext('FlowEditorContext');
10
+ const { stepsInputArgs, flowStateStore, flowStore, previewArgs } = getContext('FlowEditorContext');
11
11
  let inputCheck = $state({});
12
12
  $effect(() => {
13
13
  isValid = allTrue(inputCheck) ?? false;
@@ -17,11 +17,11 @@ $effect(() => {
17
17
  let lkeys = Object.keys(schema?.properties ?? {});
18
18
  if (schema?.properties && JSON.stringify(lkeys) != JSON.stringify(keys)) {
19
19
  keys = lkeys;
20
- untrack(() => testSteps?.removeExtraKey(mod.id, keys));
20
+ untrack(() => stepsInputArgs?.removeExtraKey(mod.id, keys));
21
21
  }
22
22
  });
23
23
  function plugIt(argName) {
24
- testSteps?.setEvaluatedStepArg(mod.id, argName, $state.snapshot(evalValue(argName, mod, pickableProperties, true)));
24
+ stepsInputArgs?.setEvaluatedStepArg(mod.id, argName, $state.snapshot(evalValue(argName, mod, pickableProperties, true)));
25
25
  }
26
26
  let editor = $state({});
27
27
  // Animation and highlighting for focusArg
@@ -53,70 +53,77 @@ async function loadResourceTypes() {
53
53
  resourceTypes = await getResourceTypes();
54
54
  }
55
55
  loadResourceTypes();
56
- onMount(() => {
57
- if (!testSteps) {
58
- sendUserToast('testSteps module not initialized. Preview will not work.', true);
56
+ let initialized = $state(false);
57
+ $effect.pre(() => {
58
+ if (!initialized) {
59
+ if (stepsInputArgs) {
60
+ stepsInputArgs?.updateStepArgs(mod.id, flowStateStore.val, flowStore?.val, previewArgs?.val);
61
+ initialized = true;
62
+ }
59
63
  }
60
- testSteps?.updateStepArgs(mod.id, flowStateStore.val, flowStore?.val, previewArgs?.val);
61
64
  });
62
65
  </script>
63
66
 
64
67
  <div class="w-full pt-2" data-popover>
65
- {#if keys.length > 0}
66
- {#each keys as argName, i (argName)}
67
- {#if Object.keys(schema.properties ?? {}).includes(argName)}
68
- <div
69
- class={twMerge(
70
- 'flex gap-2',
71
- animateArg === argName && 'animate-pulse ring-2 ring-offset-2 ring-blue-500 rounded'
72
- )}
73
- data-arg={argName}
74
- >
75
- {#if schema?.properties?.[argName]}
76
- <ArgInput
77
- {resourceTypes}
78
- minW={false}
79
- autofocus={autofocus && !focusArg && i == 0}
80
- label={argName}
81
- description={schema.properties[argName].description}
82
- bind:value={
83
- () => testSteps?.getStepInputArgs(mod.id, argName),
84
- (v) => testSteps?.setStepInputArgs(mod.id, argName, v)
85
- }
86
- type={schema.properties[argName].type}
87
- oneOf={schema.properties[argName].oneOf}
88
- required={schema?.required?.includes(argName)}
89
- pattern={schema.properties[argName].pattern}
90
- bind:editor={editor[argName]}
91
- bind:valid={inputCheck[argName]}
92
- defaultValue={schema.properties[argName].default}
93
- enum_={schema.properties[argName].enum}
94
- format={schema.properties[argName].format}
95
- contentEncoding={schema.properties[argName].contentEncoding}
96
- properties={schema.properties[argName].properties}
97
- nestedRequired={schema.properties[argName].required}
98
- itemsType={schema.properties[argName].items}
99
- extra={schema.properties[argName]}
100
- nullable={schema.properties[argName].nullable}
101
- title={schema.properties[argName].title}
102
- placeholder={schema.properties[argName].placeholder}
103
- />
104
- {/if}
105
- {#if testSteps?.isArgManuallySet(mod.id, argName)}
106
- <div class="pt-6 mt-0.5">
107
- <Button
108
- on:click={() => {
109
- plugIt(argName)
110
- }}
111
- size="sm"
112
- variant="border"
113
- color="light"
114
- title="Re-evaluate input step"><RefreshCw size={14} /></Button
115
- >
116
- </div>
117
- {/if}
118
- </div>
119
- {/if}
120
- {/each}
68
+ {#if initialized}
69
+ {#if keys.length > 0}
70
+ {#each keys as argName, i (argName)}
71
+ {#if Object.keys(schema.properties ?? {}).includes(argName)}
72
+ <div
73
+ class={twMerge(
74
+ 'flex gap-2',
75
+ animateArg === argName && 'animate-pulse ring-2 ring-offset-2 ring-blue-500 rounded'
76
+ )}
77
+ data-arg={argName}
78
+ >
79
+ {#if schema?.properties?.[argName]}
80
+ <ArgInput
81
+ {resourceTypes}
82
+ minW={false}
83
+ autofocus={autofocus && !focusArg && i == 0}
84
+ label={argName}
85
+ description={schema.properties[argName].description}
86
+ bind:value={
87
+ () => stepsInputArgs?.getStepInputArgs(mod.id, argName),
88
+ (v) => stepsInputArgs?.setStepInputArgs(mod.id, argName, v)
89
+ }
90
+ type={schema.properties[argName].type}
91
+ oneOf={schema.properties[argName].oneOf}
92
+ required={schema?.required?.includes(argName)}
93
+ pattern={schema.properties[argName].pattern}
94
+ bind:editor={editor[argName]}
95
+ bind:valid={inputCheck[argName]}
96
+ defaultValue={schema.properties[argName].default}
97
+ enum_={schema.properties[argName].enum}
98
+ format={schema.properties[argName].format}
99
+ contentEncoding={schema.properties[argName].contentEncoding}
100
+ properties={schema.properties[argName].properties}
101
+ nestedRequired={schema.properties[argName].required}
102
+ itemsType={schema.properties[argName].items}
103
+ extra={schema.properties[argName]}
104
+ nullable={schema.properties[argName].nullable}
105
+ title={schema.properties[argName].title}
106
+ placeholder={schema.properties[argName].placeholder}
107
+ />
108
+ {/if}
109
+ {#if stepsInputArgs?.isArgManuallySet(mod.id, argName)}
110
+ <div class="pt-6 mt-0.5">
111
+ <Button
112
+ on:click={() => {
113
+ plugIt(argName)
114
+ }}
115
+ size="sm"
116
+ variant="border"
117
+ color="light"
118
+ title="Re-evaluate input step"><RefreshCw size={14} /></Button
119
+ >
120
+ </div>
121
+ {/if}
122
+ </div>
123
+ {/if}
124
+ {/each}
125
+ {/if}
126
+ {:else}
127
+ <div class="text-center text-sm text-tertiary"> Loading test step arguments... </div>
121
128
  {/if}
122
129
  </div>
@@ -7,18 +7,16 @@ import { Pane, Splitpanes } from 'svelte-splitpanes';
7
7
  import { getContext } from 'svelte';
8
8
  import { getStringError } from './copilot/chat/utils';
9
9
  import AiAgentLogViewer from './AIAgentLogViewer.svelte';
10
- let { lang, editor, diffEditor, loopStatus = undefined, lastJob = undefined, scriptProgress = $bindable(undefined), testJob = undefined, mod, testIsLoading = false, disableMock = false, disableHistory = false, onUpdateMock, loadingJob = false, tagLabel = undefined } = $props();
11
- const { testSteps } = getContext('FlowEditorContext');
12
- let selectedJob = $state(undefined);
13
- let preview = $state(undefined);
10
+ let { lang, editor, diffEditor, loopStatus = undefined, scriptProgress = $bindable(undefined), testJob = undefined, mod, testIsLoading = false, disableMock = false, disableHistory = false, onUpdateMock, loadingJob = false, tagLabel = undefined } = $props();
11
+ const { stepsInputArgs } = getContext('FlowEditorContext');
14
12
  let jobProgressReset = $state(() => { });
15
- $effect(() => {
16
- if (preview != undefined && testJob) {
17
- preview = undefined;
18
- }
19
- });
20
- let forceJson = $state(false);
13
+ let outputPickerInner = $state(undefined);
14
+ export function getOutputPickerInner() {
15
+ return outputPickerInner;
16
+ }
17
+ const selectedJob = $derived.by(() => outputPickerInner?.getSelectedJob?.() ?? undefined);
21
18
  const logJob = $derived(testJob ?? selectedJob);
19
+ const preview = $derived.by(() => outputPickerInner?.getPreview?.());
22
20
  </script>
23
21
 
24
22
  <Splitpanes horizontal>
@@ -33,7 +31,6 @@ const logJob = $derived(testJob ?? selectedJob);
33
31
  {/if}
34
32
 
35
33
  <OutputPickerInner
36
- {lastJob}
37
34
  {testJob}
38
35
  fullResult
39
36
  moduleId={mod.id}
@@ -41,24 +38,22 @@ const logJob = $derived(testJob ?? selectedJob);
41
38
  getLogs
42
39
  {onUpdateMock}
43
40
  mock={mod.mock}
44
- bind:forceJson
45
- bind:selectedJob
46
41
  isLoading={testIsLoading || loadingJob}
47
- bind:preview
48
42
  path={`path` in mod.value ? mod.value.path : ''}
49
43
  {loopStatus}
50
44
  {disableMock}
51
45
  {disableHistory}
46
+ bind:this={outputPickerInner}
52
47
  >
53
48
  {#snippet copilot_fix()}
54
- {#if lang && editor && diffEditor && testSteps.getStepArgs(mod.id) && selectedJob?.type === 'CompletedJob' && !selectedJob.success && getStringError(selectedJob.result)}
49
+ {#if lang && editor && diffEditor && stepsInputArgs.getStepArgs(mod.id) && selectedJob?.type === 'CompletedJob' && !selectedJob.success && getStringError(selectedJob.result)}
55
50
  <ScriptFix {lang} />
56
51
  {/if}
57
52
  {/snippet}
58
53
  </OutputPickerInner>
59
54
  </Pane>
60
55
  <Pane size={35} minSize={10}>
61
- {#if (mod.mock?.enabled && preview != 'job') || preview == 'mock'}
56
+ {#if (mod.mock?.enabled && preview !== 'job' && testJob?.type !== 'QueuedJob') || preview === 'mock'}
62
57
  <LogViewer
63
58
  small
64
59
  content={undefined}
@@ -82,9 +77,9 @@ const logJob = $derived(testJob ?? selectedJob);
82
77
  jobId={logJob?.id}
83
78
  duration={logJob?.['duration_ms']}
84
79
  mem={logJob?.['mem_peak']}
85
- content={logJob?.logs}
80
+ content={logJob?.['logs']}
86
81
  isLoading={(testIsLoading && logJob?.['running'] == false) || loadingJob}
87
- tag={logJob?.tag}
82
+ tag={logJob?.['tag']}
88
83
  {tagLabel}
89
84
  />
90
85
  {/if}
@@ -5,17 +5,17 @@ import { getContext } from 'svelte';
5
5
  import JobLoader, {} from './JobLoader.svelte';
6
6
  import { getStepHistoryLoaderContext } from './stepHistoryLoader.svelte';
7
7
  import { loadSchemaFromModule } from './flows/flowInfers';
8
- let { mod, testJob = $bindable(undefined), testIsLoading = $bindable(false), noEditor = false, scriptProgress = $bindable(undefined) } = $props();
9
- const { flowStore, flowStateStore, pathStore, testSteps, previewArgs, modulesTestStates } = getContext('FlowEditorContext');
8
+ let { mod, testJob = $bindable(undefined), testIsLoading = $bindable(false), noEditor = false, scriptProgress = $bindable(undefined), onJobDone } = $props();
9
+ const { flowStore, flowStateStore, pathStore, stepsInputArgs, previewArgs, modulesTestStates } = getContext('FlowEditorContext');
10
10
  let jobLoader = $state(undefined);
11
11
  let jobProgressReset = () => { };
12
12
  let stepHistoryLoader = getStepHistoryLoaderContext();
13
13
  export function runTestWithStepArgs() {
14
- runTest(testSteps.getStepArgs(mod.id));
14
+ runTest(stepsInputArgs.getStepArgs(mod.id));
15
15
  }
16
16
  export function loadArgsAndRunTest() {
17
- testSteps?.updateStepArgs(mod.id, flowStateStore.val, flowStore?.val, previewArgs?.val);
18
- runTest(testSteps.getStepArgs(mod.id));
17
+ stepsInputArgs?.updateStepArgs(mod.id, flowStateStore.val, flowStore?.val, previewArgs?.val);
18
+ runTest(stepsInputArgs.getStepArgs(mod.id));
19
19
  }
20
20
  export async function runTest(args) {
21
21
  // Not defined if JobProgressBar not loaded
@@ -92,6 +92,7 @@ function jobDone(testJob) {
92
92
  if (modulesTestStates.states[mod.id]) {
93
93
  modulesTestStates.states[mod.id].testJob = testJob;
94
94
  }
95
+ onJobDone?.();
95
96
  }
96
97
  export function cancelJob() {
97
98
  modulesTestStates.states[mod.id]?.cancel?.();
@@ -129,7 +130,10 @@ modulesTestStates.states[mod.id] = {
129
130
  }
130
131
  }
131
132
  }
132
- bind:job={modulesTestStates.states[mod.id].testJob}
133
+ bind:job={
134
+ () => modulesTestStates.states[mod.id]?.testJob,
135
+ (v) => modulesTestStates.states[mod.id] && (modulesTestStates.states[mod.id].testJob = v)
136
+ }
133
137
  loadPlaceholderJobOnStart={{
134
138
  type: 'QueuedJob',
135
139
  id: '',
@@ -5,6 +5,7 @@ interface Props {
5
5
  testIsLoading?: boolean;
6
6
  noEditor?: boolean;
7
7
  scriptProgress?: any;
8
+ onJobDone?: () => void;
8
9
  }
9
10
  declare const ModuleTest: import("svelte").Component<Props, {
10
11
  runTestWithStepArgs: () => void;
@@ -1,10 +1,12 @@
1
- <script lang="ts">import CollapseLink from './CollapseLink.svelte';
1
+ <script lang="ts">import { untrack } from 'svelte';
2
+ import CollapseLink from './CollapseLink.svelte';
2
3
  import IconedResourceType from './IconedResourceType.svelte';
3
4
  import Toggle from './Toggle.svelte';
4
5
  import Tooltip from './Tooltip.svelte';
5
6
  import ToggleButton from './common/toggleButton-v2/ToggleButton.svelte';
6
7
  import ToggleButtonGroup from './common/toggleButton-v2/ToggleButtonGroup.svelte';
7
8
  let { value = $bindable() } = $props();
9
+ let lastValues = { domain: undefined, custom: undefined };
8
10
  function changeDomain(domain, custom) {
9
11
  if (value) {
10
12
  let baseUrl = custom ? `https://${domain}` : `https://${domain}.okta.com`;
@@ -25,8 +27,11 @@ function changeDomain(domain, custom) {
25
27
  }
26
28
  }
27
29
  let enabled = $derived(value != undefined);
28
- $effect(() => {
29
- changeDomain(value?.['domain'], value?.['custom']);
30
+ $effect.pre(() => {
31
+ if (value?.['domain'] != lastValues.domain || value?.['custom'] != lastValues.custom) {
32
+ lastValues = { domain: value?.['domain'], custom: value?.['custom'] };
33
+ untrack(() => changeDomain(value?.['domain'], value?.['custom']));
34
+ }
30
35
  });
31
36
  </script>
32
37
 
@@ -1,4 +1,4 @@
1
- <script context="module">
1
+ <script module>
2
2
  import { tick } from 'svelte'
3
3
 
4
4
  export function portal(el, options) {
@@ -50,13 +50,17 @@
50
50
 
51
51
  <script>
52
52
  /**
53
- * DOM Element or CSS Selector
54
- * @type { HTMLElement|string}
53
+ * @typedef {Object} Props
54
+ * @property { HTMLElement|string} [target] - DOM Element or CSS Selector
55
+ * @property {any} [name]
56
+ * @property {string|undefined} [class]
57
+ * @property {import('svelte').Snippet} [children]
55
58
  */
56
- export let target = 'body'
57
- export let name = undefined
59
+
60
+ /** @type {Props} */
61
+ let { target = 'body', name = undefined, class: clazz = undefined, children } = $props()
58
62
  </script>
59
63
 
60
- <div use:portal={{ target, name }} hidden class={$$props.class}>
61
- <slot />
64
+ <div use:portal={{ target, name }} hidden class={clazz}>
65
+ {@render children?.()}
62
66
  </div>