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
@@ -19,7 +19,7 @@ import { Pin, History, Pen, Check, X, Loader2, Pencil } from 'lucide-svelte';
19
19
  import ObjectViewer from '../../propertyPicker/ObjectViewer.svelte';
20
20
  import StepHistory from './StepHistory.svelte';
21
21
  import { Popover } from '../../meltComponents';
22
- import { untrack } from 'svelte';
22
+ import { getContext, untrack } from 'svelte';
23
23
  import { Tooltip } from '../../meltComponents';
24
24
  import DisplayResult from '../../DisplayResult.svelte';
25
25
  import OutputBadge from './OutputBadge.svelte';
@@ -27,7 +27,7 @@ import { twMerge } from 'tailwind-merge';
27
27
  import DisplayResultControlBar from '../../DisplayResultControlBar.svelte';
28
28
  import { base } from '../../../base';
29
29
  import { fade } from 'svelte/transition';
30
- let { lastJob = undefined, testJob = undefined, prefix = '', allowCopy = false, connectingData = undefined, mock = $bindable({ enabled: false }), moduleId = '', fullResult = false, closeOnOutsideClick = false, getLogs = false, selectedJob = $bindable(undefined), forceJson = $bindable(false), isLoading = $bindable(false), preview = $bindable(undefined), hideHeaderBar = false, simpleViewer = undefined, path = '', loopStatus = undefined, customHeight = undefined, rightMargin = false, disableMock = false, disableHistory = false, derivedHistoryOpen = $bindable(false), historyOffset = { mainAxis: 8, crossAxis: -4.5 }, clazz, copilot_fix, onSelect, onUpdateMock, onEditInput, selectionId, initial, customEmptyJobMessage } = $props();
30
+ let { testJob, prefix = '', allowCopy = false, connectingData = undefined, mock = $bindable({ enabled: false }), moduleId = '', fullResult = false, closeOnOutsideClick = false, getLogs = false, isLoading = $bindable(false), hideHeaderBar = false, simpleViewer = undefined, path = '', loopStatus = undefined, customHeight = undefined, rightMargin = false, disableMock = false, disableHistory = false, historyOffset = { mainAxis: 8, crossAxis: -4.5 }, clazz, copilot_fix, onSelect, onUpdateMock, onEditInput, selectionId, initial, customEmptyJobMessage } = $props();
31
31
  let jsonView = $state(false);
32
32
  let clientHeight = $state(0);
33
33
  let tmpMock = $state(undefined);
@@ -36,6 +36,8 @@ let stepHistoryPopover = $state(undefined);
36
36
  let historyOpen = $state(false);
37
37
  let contentEl = $state(undefined);
38
38
  let hasOverflow = $state(false);
39
+ let preview = $state(undefined);
40
+ let selectedJob = $state(undefined);
39
41
  function checkOverflow() {
40
42
  if (contentEl) {
41
43
  hasOverflow = contentEl.scrollHeight > contentEl.clientHeight;
@@ -45,22 +47,18 @@ function selectJob(nJob) {
45
47
  if (nJob && (nJob.result_stream || nJob.type == 'CompletedJob')) {
46
48
  selectedJob = nJob;
47
49
  }
48
- else if (job && (job.result_stream || job.type == 'CompletedJob')) {
49
- selectedJob = job;
50
+ else if (lastJob && (lastJob.result_stream || lastJob.type == 'CompletedJob')) {
51
+ selectedJob = lastJob;
50
52
  }
51
53
  else {
52
54
  selectedJob = undefined;
53
55
  }
54
56
  }
55
57
  $effect(() => {
56
- if (!job || !(job.result_stream || job.type == 'CompletedJob')) {
58
+ if (!lastJob || !(lastJob.result_stream || lastJob.type == 'CompletedJob')) {
57
59
  return;
58
60
  }
59
- selectJob(job);
60
- if (job.preview && mock?.enabled) {
61
- preview = 'job';
62
- job.preview = false;
63
- }
61
+ selectJob(lastJob);
64
62
  });
65
63
  function togglePreview(nPrev) {
66
64
  if (!nPrev && preview === 'job') {
@@ -78,6 +76,8 @@ let displayResultJob = $state(undefined);
78
76
  let displayResultMock = $state(undefined);
79
77
  let toolbarLocationJob = $state(undefined);
80
78
  let toolbarLocationMock = $state(undefined);
79
+ const flowEditorContext = getContext('FlowEditorContext');
80
+ const flowStateStore = flowEditorContext?.flowStateStore;
81
81
  function updateCanEditWithDblClick(newValue) {
82
82
  canEditWithDblClick = newValue;
83
83
  if (debounceTimeout) {
@@ -129,14 +129,33 @@ function togglePin() {
129
129
  togglePreview(undefined);
130
130
  }
131
131
  }
132
- let mockUpdateStatus = $derived(preview === 'mock' && !mock?.enabled
132
+ function updateLastJob() {
133
+ if (testJob) {
134
+ return testJob;
135
+ }
136
+ if (!flowStateStore ||
137
+ !moduleId ||
138
+ flowStateStore.val[moduleId]?.previewResult === 'never tested this far') {
139
+ return;
140
+ }
141
+ return {
142
+ id: flowStateStore.val[moduleId]?.previewJobId ?? '',
143
+ result: flowStateStore.val[moduleId]?.previewResult,
144
+ type: 'CompletedJob',
145
+ success: flowStateStore.val[moduleId]?.previewSuccess ?? undefined
146
+ };
147
+ }
148
+ const lastJob = $derived.by(updateLastJob);
149
+ export function setJobPreview() {
150
+ if (mock?.enabled) {
151
+ preview = 'job';
152
+ }
153
+ }
154
+ const mockUpdateStatus = $derived(preview === 'mock' && !mock?.enabled
133
155
  ? 'restore'
134
- : preview === 'job' && mock?.enabled && selectedJob?.type === 'CompletedJob'
156
+ : preview === 'job' && mock?.enabled && selectedJob?.['type'] === 'CompletedJob'
135
157
  ? 'override'
136
158
  : undefined);
137
- $effect(() => {
138
- derivedHistoryOpen = historyOpen;
139
- });
140
159
  $effect(() => {
141
160
  if (displayResultJob && typeof displayResultJob.getToolbarLocation === 'function') {
142
161
  toolbarLocationJob = displayResultJob.getToolbarLocation();
@@ -159,18 +178,50 @@ $effect(() => {
159
178
  untrack(() => updateCanEditWithDblClick(newValue));
160
179
  }
161
180
  });
162
- let job = $derived.by(() => {
163
- if (testJob) {
164
- return { ...testJob, preview: testJob.type === 'CompletedJob' };
165
- }
166
- if (lastJob) {
167
- return { ...lastJob, preview: false };
168
- }
169
- return undefined;
170
- });
171
181
  let popoverHeight = $derived(customHeight ?? (clientHeight > 0 ? clientHeight : 0));
172
- const isLoadingAndNotMock = $derived(isLoading && job?.result_stream === undefined && !mock?.enabled);
182
+ // If a test job is running, we override the preview to show the test job
183
+ const executingTestJob = $derived(testJob && testJob.type === 'QueuedJob');
184
+ const isLoadingAndNotMock = $derived(isLoading && lastJob?.result_stream === undefined && (!mock?.enabled || executingTestJob));
173
185
  const copilot_fix_render = $derived(copilot_fix);
186
+ export function getPreview() {
187
+ return preview;
188
+ }
189
+ async function selectJobFromHistory({ detail }) {
190
+ if (!detail) {
191
+ togglePreview(undefined);
192
+ return;
193
+ }
194
+ if (detail === 'mock') {
195
+ if (mock?.enabled) {
196
+ togglePreview(undefined);
197
+ return;
198
+ }
199
+ togglePreview('mock');
200
+ return;
201
+ }
202
+ if (detail.id === lastJob?.id && !mock?.enabled) {
203
+ togglePreview(undefined);
204
+ return;
205
+ }
206
+ isLoading = true;
207
+ try {
208
+ const fullJob = await detail.getFullJob();
209
+ if (fullJob) {
210
+ selectJob(fullJob);
211
+ togglePreview('job');
212
+ }
213
+ }
214
+ finally {
215
+ isLoading = false;
216
+ }
217
+ }
218
+ export function getHistoryOpen() {
219
+ return historyOpen;
220
+ }
221
+ export function getSelectedJob() {
222
+ return selectedJob;
223
+ }
224
+ const noHistory = $derived(loopStatus ? (loopStatus.type === 'self' ? 'isLoop' : 'isInsideLoop') : undefined);
174
225
  </script>
175
226
 
176
227
  <div
@@ -178,6 +229,7 @@ const copilot_fix_render = $derived(copilot_fix);
178
229
  bind:clientHeight
179
230
  style={canEditWithDblClick ? 'cursor: text;' : ''}
180
231
  >
232
+ <!-- Top toolbar -->
181
233
  <div
182
234
  class={twMerge(
183
235
  'text-xs px-1',
@@ -193,89 +245,24 @@ const copilot_fix_render = $derived(copilot_fix);
193
245
  )}
194
246
  >
195
247
  <div class="flex flex-row items-center gap-0.5">
248
+ <!-- History picker -->
196
249
  {#if !disableHistory}
197
- <Popover
198
- bind:this={stepHistoryPopover}
199
- floatingConfig={{
200
- strategy: 'fixed',
201
- placement: 'left-start',
202
- offset: historyOffset,
203
- gutter: 0 // hack to make offset effective, see https://github.com/melt-ui/melt-ui/issues/528
204
- }}
205
- contentClasses="w-[225px] overflow-hidden"
206
- {closeOnOutsideClick}
207
- usePointerDownOutside={closeOnOutsideClick}
208
- disablePopup={!!connectingData || jsonView}
209
- bind:isOpen={historyOpen}
210
- >
211
- {#snippet trigger()}
212
- <Button
213
- color="light"
214
- size="xs2"
215
- variant="contained"
216
- btnClasses="bg-surface h-[27px]"
217
- startIcon={{ icon: History }}
218
- nonCaptureEvent
219
- />
220
- {/snippet}
221
- {#snippet content()}
222
- <div class="rounded-[inherit]" style={`height: ${popoverHeight}px`}>
223
- <StepHistory
224
- {moduleId}
225
- {getLogs}
226
- on:select={async ({ detail }) => {
227
- if (!detail) {
228
- togglePreview(undefined)
229
- return
230
- }
231
- if (detail === 'mock') {
232
- if (mock?.enabled) {
233
- togglePreview(undefined)
234
- return
235
- }
236
- togglePreview('mock')
237
- return
238
- }
239
- if (detail.id === job?.id && !mock?.enabled) {
240
- togglePreview(undefined)
241
- return
242
- }
243
-
244
- // Create a timeout to show loading state after 200ms
245
- const loadingTimeout = setTimeout(() => {
246
- isLoading = true
247
- }, 200)
248
-
249
- try {
250
- const fullJob = await detail.getFullJob()
251
- if (fullJob) {
252
- selectJob(fullJob)
253
- togglePreview('job')
254
- }
255
- } finally {
256
- // Clear the timeout if operation completed before 200ms
257
- clearTimeout(loadingTimeout)
258
- isLoading = false
259
- }
260
- }}
261
- mockValue={mock?.return_value}
262
- mockEnabled={mock?.enabled}
263
- {path}
264
- noHistory={loopStatus
265
- ? loopStatus.type === 'self'
266
- ? 'isLoop'
267
- : 'isInsideLoop'
268
- : undefined}
269
- />
270
- </div>
271
- {/snippet}
272
- </Popover>
250
+ {@render historyPicker()}
273
251
  {/if}
274
- {#if !isLoadingAndNotMock || mock?.enabled}
252
+ <!-- Badge-->
253
+ {#if executingTestJob}
254
+ <OutputBadge
255
+ job={testJob}
256
+ class={twMerge(
257
+ 'min-w-16 min-h-[23px] text-secondary',
258
+ preview ? 'bg-surface shadow-sm' : ''
259
+ )}
260
+ />
261
+ {:else if !isLoadingAndNotMock || mock?.enabled}
275
262
  <div
276
263
  class={twMerge(
277
264
  'w-grow min-w-0 flex gap-1 items-center h-[27px] rounded-md group',
278
- preview || selectedJob?.id !== job?.id ? 'p-[2px] bg-surface-secondary' : ''
265
+ preview || selectedJob?.id !== lastJob?.id ? 'p-[2px] bg-surface-secondary' : ''
279
266
  )}
280
267
  >
281
268
  {#if loopStatus?.type === 'self'}
@@ -311,7 +298,7 @@ const copilot_fix_render = $derived(copilot_fix);
311
298
  job={selectedJob}
312
299
  class={twMerge(
313
300
  'min-w-16 text-secondary',
314
- preview || selectedJob?.id !== job?.id ? 'bg-surface shadow-sm h-[23px]' : ''
301
+ preview || selectedJob?.id !== lastJob?.id ? 'bg-surface shadow-sm h-[23px]' : ''
315
302
  )}
316
303
  />
317
304
  {/if}
@@ -329,17 +316,9 @@ const copilot_fix_render = $derived(copilot_fix);
329
316
  >
330
317
  {/if}
331
318
  </div>
332
- {:else if testJob}
333
- <!-- {JSON.stringify(testJob)} -->
334
- <OutputBadge
335
- job={testJob}
336
- class={twMerge(
337
- 'min-w-16 text-secondary',
338
- preview || testJob?.id !== job?.id ? 'bg-surface shadow-sm h-[23px]' : ''
339
- )}
340
- />
341
319
  {/if}
342
320
 
321
+ <!-- Pin button -->
343
322
  {#if !disableMock && !isLoadingAndNotMock}
344
323
  <Tooltip disablePopup={mock?.enabled}>
345
324
  <Button
@@ -368,6 +347,7 @@ const copilot_fix_render = $derived(copilot_fix);
368
347
  {/if}
369
348
 
370
349
  {#if jsonView}
350
+ <!-- Save button -->
371
351
  <Button
372
352
  size="xs2"
373
353
  color="green"
@@ -388,6 +368,7 @@ const copilot_fix_render = $derived(copilot_fix);
388
368
  }}
389
369
  disabled={!!error || !tmpMock}
390
370
  />
371
+ <!-- Cancel button -->
391
372
  <Button
392
373
  size="xs2"
393
374
  color="red"
@@ -399,7 +380,8 @@ const copilot_fix_render = $derived(copilot_fix);
399
380
  tmpMock = undefined
400
381
  }}
401
382
  />
402
- {:else if mock?.enabled && !preview}
383
+ {:else if mock?.enabled && !preview && !executingTestJob}
384
+ <!-- Edit pin button -->
403
385
  <Tooltip disablePopup={mock?.enabled}>
404
386
  <Button
405
387
  size="xs2"
@@ -510,6 +492,7 @@ const copilot_fix_render = $derived(copilot_fix);
510
492
  <Loader2 class="animate-spin" />
511
493
  </div>
512
494
  {:else if connectingData !== undefined || simpleViewer}
495
+ <!-- Display data for input connections -->
513
496
  <ObjectViewer
514
497
  json={moduleId
515
498
  ? {
@@ -526,6 +509,7 @@ const copilot_fix_render = $derived(copilot_fix);
526
509
  {editKey}
527
510
  />
528
511
  {:else if jsonView}
512
+ <!-- Json editor for editing mock data -->
529
513
  {#await import('../../JsonEditor.svelte')}
530
514
  <Loader2 class="animate-spin" />
531
515
  {:then Module}
@@ -549,12 +533,12 @@ const copilot_fix_render = $derived(copilot_fix);
549
533
  class="h-full"
550
534
  />
551
535
  {/await}
552
- {:else if (mock?.enabled || preview == 'mock') && preview != 'job'}
536
+ {:else if (mock?.enabled || preview == 'mock') && preview != 'job' && !executingTestJob}
537
+ <!-- Display data for mock data -->
553
538
  {#if fullResult}
554
539
  <div class="break-words relative h-full">
555
540
  <DisplayResult
556
541
  bind:this={displayResultMock}
557
- bind:forceJson
558
542
  workspaceId={undefined}
559
543
  jobId={undefined}
560
544
  result_stream={undefined}
@@ -578,12 +562,12 @@ const copilot_fix_render = $derived(copilot_fix);
578
562
  />
579
563
  {/if}
580
564
  {:else if selectedJob != undefined && (selectedJob.result_stream || selectedJob.type == 'CompletedJob')}
565
+ <!-- Display data for job data -->
581
566
  {#if fullResult}
582
567
  <div class="break-words relative h-full">
583
568
  {#key selectedJob}
584
569
  <DisplayResult
585
570
  bind:this={displayResultJob}
586
- bind:forceJson
587
571
  workspaceId={selectedJob?.workspace_id}
588
572
  jobId={selectedJob?.id}
589
573
  result={selectedJob?.result}
@@ -611,7 +595,7 @@ const copilot_fix_render = $derived(copilot_fix);
611
595
  pureViewer={false}
612
596
  />
613
597
  {/if}
614
- {:else if !job}
598
+ {:else if !lastJob}
615
599
  <div class="flex flex-col items-center justify-center h-full">
616
600
  <p class="text-xs text-secondary">
617
601
  {customEmptyJobMessage ?? 'Test this step to see results'}{#if !disableMock}
@@ -649,6 +633,47 @@ const copilot_fix_render = $derived(copilot_fix);
649
633
  </button>
650
634
  {/snippet}
651
635
 
636
+ {#snippet historyPicker()}
637
+ <Popover
638
+ bind:this={stepHistoryPopover}
639
+ floatingConfig={{
640
+ strategy: 'fixed',
641
+ placement: 'left-start',
642
+ offset: historyOffset,
643
+ gutter: 0 // hack to make offset effective, see https://github.com/melt-ui/melt-ui/issues/528
644
+ }}
645
+ contentClasses="w-[225px] overflow-hidden"
646
+ {closeOnOutsideClick}
647
+ usePointerDownOutside={closeOnOutsideClick}
648
+ disablePopup={!!connectingData || jsonView}
649
+ bind:isOpen={historyOpen}
650
+ >
651
+ {#snippet trigger()}
652
+ <Button
653
+ color="light"
654
+ size="xs2"
655
+ variant="contained"
656
+ btnClasses="bg-surface h-[27px]"
657
+ startIcon={{ icon: History }}
658
+ nonCaptureEvent
659
+ />
660
+ {/snippet}
661
+ {#snippet content()}
662
+ <div class="rounded-[inherit]" style={`height: ${popoverHeight}px`}>
663
+ <StepHistory
664
+ {moduleId}
665
+ {getLogs}
666
+ on:select={selectJobFromHistory}
667
+ mockValue={mock?.return_value}
668
+ mockEnabled={mock?.enabled}
669
+ {path}
670
+ {noHistory}
671
+ />
672
+ </div>
673
+ {/snippet}
674
+ </Popover>
675
+ {/snippet}
676
+
652
677
  <style>
653
678
  .dbl-click-editable {
654
679
  cursor: text;
@@ -1,15 +1,5 @@
1
1
  import type { Job } from '../../../gen';
2
- type SelectedJob = ((Job | {
3
- id: string;
4
- result: unknown;
5
- type: 'CompletedJob';
6
- workspace_id: string;
7
- success: boolean;
8
- }) & {
9
- preview?: boolean;
10
- result_stream?: string;
11
- result?: unknown;
12
- }) | undefined;
2
+ import type { OutputViewerJob } from '../types';
13
3
  interface Props {
14
4
  prefix?: string;
15
5
  allowCopy?: boolean;
@@ -22,10 +12,7 @@ interface Props {
22
12
  fullResult?: boolean;
23
13
  closeOnOutsideClick?: boolean;
24
14
  getLogs?: boolean;
25
- selectedJob?: SelectedJob;
26
- forceJson?: boolean;
27
15
  isLoading?: boolean;
28
- preview?: 'mock' | 'job' | undefined;
29
16
  hideHeaderBar?: boolean;
30
17
  simpleViewer?: any | undefined;
31
18
  path?: string;
@@ -37,7 +24,6 @@ interface Props {
37
24
  rightMargin?: boolean;
38
25
  disableMock?: boolean;
39
26
  disableHistory?: boolean;
40
- lastJob?: Job;
41
27
  testJob?: Job & {
42
28
  result_stream?: string;
43
29
  };
@@ -56,6 +42,11 @@ interface Props {
56
42
  onResetInitial?: () => void;
57
43
  customEmptyJobMessage?: string;
58
44
  }
59
- declare const OutputPickerInner: import("svelte").Component<Props, {}, "preview" | "forceJson" | "mock" | "isLoading" | "selectedJob" | "derivedHistoryOpen">;
45
+ declare const OutputPickerInner: import("svelte").Component<Props, {
46
+ setJobPreview: () => void;
47
+ getPreview: () => "job" | "mock" | undefined;
48
+ getHistoryOpen: () => boolean;
49
+ getSelectedJob: () => OutputViewerJob;
50
+ }, "mock" | "isLoading">;
60
51
  type OutputPickerInner = ReturnType<typeof OutputPickerInner>;
61
52
  export default OutputPickerInner;
@@ -1,7 +1,7 @@
1
1
  import type { FlowModule, OpenFlow } from '../../gen';
2
2
  import type { FlowState } from './flowState';
3
3
  import { type PickableProperties } from './previousResults';
4
- export declare class TestSteps {
4
+ export declare class StepsInputArgs {
5
5
  #private;
6
6
  constructor();
7
7
  setStepArgsManually(moduleId: string, args: Record<string, any>): void;
@@ -19,4 +19,5 @@ export declare class TestSteps {
19
19
  }, pickableProperties: PickableProperties | undefined): void;
20
20
  updateStepArgs(id: string, flowState: FlowState | undefined, flow: OpenFlow | undefined, previewArgs: Record<string, any> | undefined): void;
21
21
  removeExtraKey(moduleId: string, keys: string[]): void;
22
+ resetManuallyEditedArgs(): void;
22
23
  }
@@ -1,6 +1,6 @@
1
1
  import { dfs, getPreviousModule, getStepPropPicker } from './previousResults';
2
2
  import { evalValue } from './utils';
3
- export class TestSteps {
3
+ export class StepsInputArgs {
4
4
  #stepsEvaluated = $state({});
5
5
  #steps = $state({});
6
6
  constructor() { }
@@ -36,8 +36,17 @@ export class TestSteps {
36
36
  this.#stepsEvaluated[moduleId][argName] = $state.snapshot(value);
37
37
  }
38
38
  isArgManuallySet(moduleId, argName) {
39
- return (JSON.stringify(this.#steps[moduleId]?.[argName]) !==
40
- JSON.stringify(this.#stepsEvaluated[moduleId]?.[argName]));
39
+ try {
40
+ const stepsValue = this.#steps[moduleId]?.[argName];
41
+ const evaluatedValue = this.#stepsEvaluated[moduleId]?.[argName];
42
+ const stepsStr = JSON.stringify(stepsValue);
43
+ const evaluatedStr = JSON.stringify(evaluatedValue);
44
+ return stepsStr !== evaluatedStr;
45
+ }
46
+ catch (error) {
47
+ console.warn(`Error in isArgManuallySet for moduleId: ${moduleId}, argName: ${argName}`, error);
48
+ return this.#steps[moduleId]?.[argName] !== this.#stepsEvaluated[moduleId]?.[argName];
49
+ }
41
50
  }
42
51
  getManuallyEditedArgs(moduleId) {
43
52
  const manuallyEditedArgs = [];
@@ -122,4 +131,7 @@ export class TestSteps {
122
131
  });
123
132
  this.#stepsEvaluated[moduleId] = nargs;
124
133
  }
134
+ resetManuallyEditedArgs() {
135
+ this.#steps = $state.snapshot(this.#stepsEvaluated);
136
+ }
125
137
  }
@@ -1,4 +1,4 @@
1
- import type { OpenFlow } from '../../gen';
1
+ import type { Job, OpenFlow } from '../../gen';
2
2
  import type { History } from '../../history.svelte';
3
3
  import type { Writable } from 'svelte/store';
4
4
  import type ScriptEditorDrawer from './content/ScriptEditorDrawer.svelte';
@@ -7,12 +7,13 @@ import type { FlowBuilderWhitelabelCustomUi } from '../custom_ui';
7
7
  import type Editor from '../Editor.svelte';
8
8
  import type SimpleEditor from '../SimpleEditor.svelte';
9
9
  import type { StateStore } from '../../utils';
10
- import type { TestSteps } from './testSteps.svelte';
10
+ import type { StepsInputArgs } from './stepsInputArgs.svelte';
11
11
  import type { Asset, AssetWithAccessType } from '../assets/lib';
12
12
  import type S3FilePicker from '../S3FilePicker.svelte';
13
13
  import type DbManagerDrawer from '../DBManagerDrawer.svelte';
14
14
  import type ResourceEditorDrawer from '../ResourceEditorDrawer.svelte';
15
15
  import type { ModulesTestStates } from '../modulesTest.svelte';
16
+ import type { ButtonProp } from '../DiffEditor.svelte';
16
17
  export type FlowInput = Record<string, {
17
18
  flowStepWarnings?: Record<string, {
18
19
  message: string;
@@ -38,6 +39,8 @@ export type CurrentEditor = (({
38
39
  hideDiffMode: () => void;
39
40
  diffMode: boolean;
40
41
  lastDeployedCode: string | undefined;
42
+ setDiffOriginal?: (code: string) => void;
43
+ setDiffButtons?: (buttons: ButtonProp[]) => void;
41
44
  } | {
42
45
  type: 'iterator';
43
46
  editor: SimpleEditor;
@@ -57,7 +60,7 @@ export type FlowEditorContext = {
57
60
  flowStore: StateStore<ExtendedOpenFlow>;
58
61
  flowInputEditorState: Writable<FlowInputEditorState>;
59
62
  flowStateStore: StateStore<FlowState>;
60
- testSteps: TestSteps;
63
+ stepsInputArgs: StepsInputArgs;
61
64
  saveDraft: () => void;
62
65
  initialPathStore: Writable<string>;
63
66
  fakeInitialPath: string;
@@ -79,3 +82,13 @@ export type FlowGraphAssetContext = StateStore<{
79
82
  additionalAssetsMap: Record<string, AssetWithAccessType[]>;
80
83
  computeAssetsCount: (asset: Asset) => number;
81
84
  }>;
85
+ export type OutputViewerJob = ((Job | {
86
+ id: string;
87
+ result: unknown;
88
+ type: 'CompletedJob';
89
+ workspace_id: string;
90
+ success: boolean;
91
+ }) & {
92
+ result_stream?: string;
93
+ result?: unknown;
94
+ }) | undefined;
@@ -42,6 +42,9 @@ export function evalValue(k, mod, pickableProperties, showError) {
42
42
  v = undefined;
43
43
  }
44
44
  }
45
+ if (v === NEVER_TESTED_THIS_FAR) {
46
+ v = undefined;
47
+ }
45
48
  return v;
46
49
  }
47
50
  export function filteredContentForExport(flow) {
@@ -303,7 +303,7 @@ let graph = $derived.by(() => {
303
303
  suspendStatus,
304
304
  flowHasChanged,
305
305
  additionalAssetsMap: flowGraphAssetsCtx?.val.additionalAssetsMap
306
- }, untrack(() => failureModule), untrack(() => preprocessorModule), eventHandler, success, $useDataflow, untrack(() => $selectedId), moving, simplifiableFlow, triggerNode ? path : undefined, expandedSubflows);
306
+ }, untrack(() => failureModule), preprocessorModule, eventHandler, success, $useDataflow, untrack(() => $selectedId), moving, simplifiableFlow, triggerNode ? path : undefined, expandedSubflows);
307
307
  });
308
308
  $effect(() => {
309
309
  ;
@@ -7,7 +7,7 @@ export const BELOW_ADDITIONAL_OFFSET = 19;
7
7
  export const AI_TOOL_CALL_PREFIX = '_wm_ai_agent_tool_call';
8
8
  export const AI_TOOL_MESSAGE_PREFIX = '_wm_ai_agent_message';
9
9
  const ROW_WIDTH = 275;
10
- const NEW_TOOL_NODE_WIDTH = 40;
10
+ const NEW_TOOL_NODE_WIDTH = 50;
11
11
  const MAX_TOOLS_PER_ROW = 2;
12
12
  let computeAIToolNodesCache;
13
13
  export function getToolCallId(idx, agentModuleId, moduleId) {
@@ -100,13 +100,13 @@ export function computeAIToolNodes(nodes, eventHandlers, insertable, flowModuleS
100
100
  id: `${node.id}-tool-${tool.id}`,
101
101
  width: inputToolWidth,
102
102
  position: {
103
- x: tools.length === 1
103
+ x: (tools.length === 1
104
104
  ? (ROW_WIDTH - inputToolWidth) / 2
105
105
  : (i + 1) % 2 === 0
106
106
  ? inputToolWidth + inputToolXGap
107
107
  : isLastRow && tools.length % 2 === 1
108
108
  ? (ROW_WIDTH - inputToolWidth) / 2
109
- : 0,
109
+ : 0) + node.data.offset,
110
110
  y: baseOffset +
111
111
  rowOffset *
112
112
  (agentActions
@@ -132,7 +132,7 @@ export function computeAIToolNodes(nodes, eventHandlers, insertable, flowModuleS
132
132
  parentId: node.id,
133
133
  width: NEW_TOOL_NODE_WIDTH,
134
134
  position: {
135
- x: (ROW_WIDTH - NEW_TOOL_NODE_WIDTH) / 2,
135
+ x: (ROW_WIDTH - NEW_TOOL_NODE_WIDTH) / 2 + node.data.offset,
136
136
  y: baseOffset + rowOffset
137
137
  }
138
138
  });