windmill-components 1.532.0 → 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 (135) hide show
  1. package/package/components/ArgInput.svelte +25 -18
  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 +42 -51
  8. package/package/components/EditableSchemaForm.svelte.d.ts +2 -3
  9. package/package/components/Editor.svelte +30 -9
  10. package/package/components/Editor.svelte.d.ts +5 -0
  11. package/package/components/FlowBuilder.svelte +7 -4
  12. package/package/components/FlowPreviewContent.svelte +3 -3
  13. package/package/components/FlowStatusViewer.svelte +28 -0
  14. package/package/components/FlowStatusViewerInner.svelte +72 -20
  15. package/package/components/FlowStatusViewerInner.svelte.d.ts +7 -0
  16. package/package/components/ModulePreview.svelte +2 -1
  17. package/package/components/ModulePreview.svelte.d.ts +1 -0
  18. package/package/components/ModulePreviewForm.svelte +72 -65
  19. package/package/components/ModulePreviewResultViewer.svelte +13 -18
  20. package/package/components/ModuleTest.svelte +6 -5
  21. package/package/components/ModuleTest.svelte.d.ts +1 -0
  22. package/package/components/OktaSetting.svelte +8 -3
  23. package/package/components/Portal.svelte +11 -7
  24. package/package/components/Portal.svelte.d.ts +19 -39
  25. package/package/components/RunForm.svelte +2 -2
  26. package/package/components/RunForm.svelte.d.ts +1 -1
  27. package/package/components/RunFormAdvancedPopup.svelte +13 -1
  28. package/package/components/SchemaForm.svelte +1 -2
  29. package/package/components/ScriptBuilder.svelte +1 -1
  30. package/package/components/ScriptEditor.svelte +21 -7
  31. package/package/components/SimpleEditor.svelte +0 -1
  32. package/package/components/apps/components/layout/AppModal.svelte +2 -2
  33. package/package/components/apps/editor/component/ComponentNavigation.svelte +3 -2
  34. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +1 -1
  35. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +0 -1
  36. package/package/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +3 -1
  37. package/package/components/apps/editor/settingsPanel/GridCondition.svelte +3 -1
  38. package/package/components/apps/editor/settingsPanel/GridNavbar.svelte +3 -1
  39. package/package/components/apps/editor/settingsPanel/GridTab.svelte +3 -1
  40. package/package/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte +55 -53
  41. package/package/components/apps/editor/settingsPanel/TableActions.svelte +3 -1
  42. package/package/components/common/button/model.d.ts +1 -1
  43. package/package/components/common/drawer/Disposable.svelte +51 -30
  44. package/package/components/common/drawer/Disposable.svelte.d.ts +12 -44
  45. package/package/components/common/drawer/Drawer.svelte +15 -11
  46. package/package/components/copilot/MetadataGen.svelte +14 -3
  47. package/package/components/copilot/chat/AIChatInput.svelte +0 -1
  48. package/package/components/copilot/chat/AIChatManager.svelte.js +3 -3
  49. package/package/components/copilot/chat/AvailableContextList.svelte +192 -66
  50. package/package/components/copilot/chat/AvailableContextList.svelte.d.ts +2 -2
  51. package/package/components/copilot/chat/ContextElementBadge.svelte +3 -3
  52. package/package/components/copilot/chat/ContextManager.svelte.js +36 -13
  53. package/package/components/copilot/chat/ContextTextarea.svelte +21 -48
  54. package/package/components/copilot/chat/ToolContentDisplay.svelte +10 -1
  55. package/package/components/copilot/chat/ToolExecutionDisplay.svelte +3 -3
  56. package/package/components/copilot/chat/context.d.ts +7 -2
  57. package/package/components/copilot/chat/flow/FlowAIChat.svelte +110 -8
  58. package/package/components/copilot/chat/flow/core.d.ts +11 -0
  59. package/package/components/copilot/chat/flow/core.js +121 -3
  60. package/package/components/copilot/chat/flow/uiIntents.d.ts +8 -0
  61. package/package/components/copilot/chat/flow/uiIntents.js +5 -0
  62. package/package/components/copilot/chat/flow/useUiIntent.d.ts +5 -0
  63. package/package/components/copilot/chat/flow/useUiIntent.js +12 -0
  64. package/package/components/copilot/chat/monaco-adapter.d.ts +22 -4
  65. package/package/components/copilot/chat/monaco-adapter.js +55 -16
  66. package/package/components/copilot/chat/script/core.js +3 -2
  67. package/package/components/copilot/chat/shared.d.ts +3 -2
  68. package/package/components/copilot/chat/shared.js +24 -12
  69. package/package/components/copilot/lib.js +12 -7
  70. package/package/components/copilot/shared.d.ts +1 -1
  71. package/package/components/copilot/shared.js +16 -10
  72. package/package/components/flows/FlowEditor.svelte +4 -2
  73. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  74. package/package/components/flows/FlowModuleIcon.svelte +8 -8
  75. package/package/components/flows/common/FlowCardHeader.svelte +4 -1
  76. package/package/components/flows/content/FlowBranchesAllWrapper.svelte +6 -0
  77. package/package/components/flows/content/FlowBranchesOneWrapper.svelte +6 -0
  78. package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
  79. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
  80. package/package/components/flows/content/FlowInput.svelte +31 -34
  81. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
  82. package/package/components/flows/content/FlowLoop.svelte +7 -0
  83. package/package/components/flows/content/FlowModuleComponent.svelte +37 -44
  84. package/package/components/flows/content/FlowModuleScript.svelte +1 -1
  85. package/package/components/flows/content/FlowModuleSuspend.svelte +16 -18
  86. package/package/components/flows/content/FlowWhileLoop.svelte +6 -0
  87. package/package/components/flows/content/ScriptEditorDrawer.svelte +9 -11
  88. package/package/components/flows/dfs.d.ts +1 -1
  89. package/package/components/flows/dfs.js +6 -6
  90. package/package/components/flows/flowInfers.js +7 -7
  91. package/package/components/flows/flowStateUtils.svelte.js +1 -2
  92. package/package/components/flows/map/FlowModuleSchemaItem.svelte +12 -26
  93. package/package/components/flows/map/MapItem.svelte +8 -4
  94. package/package/components/flows/map/VirtualItem.svelte +1 -1
  95. package/package/components/flows/pickers/TopLevelNode.svelte +1 -1
  96. package/package/components/flows/propPicker/InputPickerInner.svelte +5 -5
  97. package/package/components/flows/propPicker/OutputPickerInner.svelte +143 -118
  98. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +7 -16
  99. package/package/components/flows/{testSteps.svelte.d.ts → stepsInputArgs.svelte.d.ts} +2 -1
  100. package/package/components/flows/{testSteps.svelte.js → stepsInputArgs.svelte.js} +15 -3
  101. package/package/components/flows/types.d.ts +16 -3
  102. package/package/components/flows/utils.js +3 -0
  103. package/package/components/graph/FlowGraphV2.svelte +1 -1
  104. package/package/components/graph/renderers/nodes/AIToolNode.svelte +4 -4
  105. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +71 -54
  106. package/package/components/propertyPicker/ObjectViewer.svelte +11 -3
  107. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +1 -1
  108. package/package/components/schema/AddPropertyV2.svelte +2 -7
  109. package/package/components/schema/AddPropertyV2.svelte.d.ts +3 -20
  110. package/package/components/schema/EditableSchemaDrawer.svelte +109 -115
  111. package/package/components/schema/EditableSchemaDrawer.svelte.d.ts +2 -1
  112. package/package/components/schema/EditableSchemaSdkWrapper.svelte +16 -3
  113. package/package/components/schema/EditableSchemaSdkWrapper.svelte.d.ts +4 -1
  114. package/package/components/schema/EditableSchemaWrapper.svelte +3 -10
  115. package/package/components/schema/FlowPropertyEditor.svelte +9 -41
  116. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +1 -1
  117. package/package/components/schema/SchemaFormDND.svelte +11 -10
  118. package/package/components/schema/SchemaFormDND.svelte.d.ts +3 -2
  119. package/package/components/schema/editable_schema_wrapper.d.ts +0 -3
  120. package/package/components/settings/PremiumInfo.svelte +7 -2
  121. package/package/components/triggers/CaptureWrapper.svelte +2 -13
  122. package/package/components/triggers/CaptureWrapper.svelte.d.ts +1 -1
  123. package/package/components/triggers/TriggersWrapper.svelte +1 -0
  124. package/package/components/triggers/http/RouteEditorInner.svelte +1 -1
  125. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +23 -20
  126. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte +15 -27
  127. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte.d.ts +7 -5
  128. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +16 -16
  129. package/package/hubPaths.json +3 -1
  130. package/package/script_helpers.d.ts +2 -2
  131. package/package/script_helpers.js +2 -0
  132. package/package/stores.d.ts +1 -0
  133. package/package/stores.js +8 -1
  134. package/package.json +2 -2
  135. package/package/components/ModulePreviewResultViewer.svelte.d.ts +0 -28
@@ -37,9 +37,7 @@ let moduleTest = $state(undefined);
37
37
  let testIsLoading = $state(false);
38
38
  let hover = $state(false);
39
39
  let connectingData = $state(undefined);
40
- let lastJob = $state(undefined);
41
40
  let outputPicker = $state(undefined);
42
- let historyOpen = $state(false);
43
41
  let testJob = $state(undefined);
44
42
  let outputPickerBarOpen = $state(false);
45
43
  let flowStateStore = $derived(flowEditorContext?.flowStateStore);
@@ -55,32 +53,13 @@ function updateConnectingData(id, pickableIds, flowPropPickerConfig, flowStateSt
55
53
  $effect(() => {
56
54
  updateConnectingData(id, pickableIds, $flowPropPickerConfig, flowStateStore);
57
55
  });
58
- function updateLastJob(flowStateStore) {
59
- if (!flowStateStore ||
60
- !id ||
61
- flowStateStore.val[id]?.previewResult === 'never tested this far') {
62
- return;
63
- }
64
- lastJob = {
65
- id: flowStateStore.val[id]?.previewJobId ?? '',
66
- result: flowStateStore.val[id]?.previewResult,
67
- type: 'CompletedJob',
68
- success: flowStateStore.val[id]?.previewSuccess ?? undefined
69
- };
70
- }
71
- $effect(() => {
72
- if (testJob && testJob.type === 'CompletedJob') {
73
- lastJob = $state.snapshot(testJob);
74
- }
75
- else if (id) {
76
- updateLastJob(flowStateStore);
77
- }
78
- });
79
56
  let isConnectingCandidate = $derived(!!id && !!$flowPropPickerConfig && !!pickableIds && Object.keys(pickableIds).includes(id));
80
57
  const outputPickerVisible = $derived(editMode && (isConnectingCandidate || alwaysShowOutputPicker) && !!id);
81
58
  const icon_render = $derived(icon);
82
59
  const action = $derived(getAiModuleAction(id));
83
60
  let testRunDropdownOpen = $state(false);
61
+ let outputPickerInner = $state(undefined);
62
+ let historyOpen = $derived.by(() => outputPickerInner?.getHistoryOpen?.() ?? false);
84
63
  </script>
85
64
 
86
65
  {#if deletable && id && editId}
@@ -145,7 +124,15 @@ let testRunDropdownOpen = $state(false);
145
124
  {@const flowStore = flowEditorContext?.flowStore.val}
146
125
  {@const mod = flowStore?.value ? dfsPreviousResults(id, flowStore, false)[0] : undefined}
147
126
  {#if mod && flowStateStore?.val?.[id]}
148
- <ModuleTest bind:this={moduleTest} {mod} bind:testIsLoading bind:testJob />
127
+ <ModuleTest
128
+ bind:this={moduleTest}
129
+ {mod}
130
+ bind:testIsLoading
131
+ bind:testJob
132
+ onJobDone={() => {
133
+ outputPickerInner?.setJobPreview?.()
134
+ }}
135
+ />
149
136
  {/if}
150
137
  {/if}
151
138
 
@@ -329,7 +316,6 @@ let testRunDropdownOpen = $state(false);
329
316
  prefix={'results'}
330
317
  connectingData={isConnecting ? connectingData : undefined}
331
318
  {mock}
332
- {lastJob}
333
319
  {testJob}
334
320
  moduleId={id}
335
321
  onSelect={selectConnection}
@@ -337,12 +323,12 @@ let testRunDropdownOpen = $state(false);
337
323
  {path}
338
324
  {loopStatus}
339
325
  rightMargin
340
- bind:derivedHistoryOpen={historyOpen}
341
326
  historyOffset={{ mainAxis: 12, crossAxis: -9 }}
342
327
  clazz="p-1"
343
328
  isLoading={testIsLoading ||
344
329
  (id ? stepHistoryLoader?.stepStates[id]?.loadingJobs : false)}
345
330
  initial={id ? stepHistoryLoader?.stepStates[id]?.initial : undefined}
331
+ bind:this={outputPickerInner}
346
332
  />
347
333
  {/snippet}
348
334
  </OutputPicker>
@@ -170,6 +170,7 @@ let parentLoop = $derived(flowStore?.val && mod ? checkIfParentLoop(flowStore.va
170
170
  {bgColor}
171
171
  {bgHoverColor}
172
172
  label={mod.summary ||
173
+ (mod.value.type === 'aiagent' ? 'AI Agent' : undefined) ||
173
174
  (mod.id === 'preprocessor'
174
175
  ? 'Preprocessor'
175
176
  : mod.id.startsWith('failure')
@@ -194,10 +195,13 @@ let parentLoop = $derived(flowStore?.val && mod ? checkIfParentLoop(flowStore.va
194
195
  {skipped}
195
196
  >
196
197
  {#snippet icon()}
197
- {@const size = mod.value.type === 'script' && mod.value.path.startsWith('hub/')
198
- ? 20
199
- : mod.value.type === "script" ? 14 : 16}
200
- <FlowModuleIcon module={mod} size={size} />
198
+ {@const size =
199
+ mod.value.type === 'script' && mod.value.path.startsWith('hub/')
200
+ ? 20
201
+ : mod.value.type === 'script'
202
+ ? 14
203
+ : 16}
204
+ <FlowModuleIcon module={mod} {size} />
201
205
  {/snippet}
202
206
  </FlowModuleSchemaItem>
203
207
  {/if}
@@ -70,7 +70,7 @@ const outputType = $derived(showJobStatus
70
70
  {selected}
71
71
  {hover}
72
72
  id={id ?? ''}
73
- isConnectingCandidate={true}
73
+ isConnectingCandidate={nodeKind !== 'result'}
74
74
  variant="virtual"
75
75
  type={outputType}
76
76
  {darkMode}
@@ -52,7 +52,7 @@ const dispatch = createEventDispatcher();
52
52
  <GitBranch size={14} />
53
53
  Branch to all
54
54
  {:else if label === 'AI Agent'}
55
- <BotIcon size={14} />
55
+ <BotIcon size={14} class="text-violet-800 dark:text-violet-400" />
56
56
  AI Agent
57
57
  {/if}
58
58
  </span>
@@ -3,11 +3,11 @@ import ObjectViewer from '../../propertyPicker/ObjectViewer.svelte';
3
3
  import { twMerge } from 'tailwind-merge';
4
4
  import { DollarSign, Pencil, RefreshCw, SquareFunction } from 'lucide-svelte';
5
5
  let { inputTransform, id, onEditInput } = $props();
6
- const { flowStore, flowStateStore, testSteps, previewArgs } = getContext('FlowEditorContext') || {};
6
+ const { flowStore, flowStateStore, stepsInputArgs, previewArgs } = getContext('FlowEditorContext') || {};
7
7
  onMount(() => {
8
- testSteps?.updateStepArgs(id, flowStateStore?.val, flowStore?.val, previewArgs?.val);
8
+ stepsInputArgs?.updateStepArgs(id, flowStateStore?.val, flowStore?.val, previewArgs?.val);
9
9
  });
10
- const input = $derived(testSteps?.getStepArgs(id));
10
+ const input = $derived(stepsInputArgs?.getStepArgs(id));
11
11
  </script>
12
12
 
13
13
  <div class="p-4 pr-6 h-full overflow-y-auto">
@@ -29,10 +29,10 @@ const input = $derived(testSteps?.getStepArgs(id));
29
29
  {:else if inputTransform[key].type === 'static'}
30
30
  <DollarSign size={12} class="text-tertiary font-mono -my-1" />
31
31
  {/if}
32
- {#if testSteps?.isArgManuallySet(id, key)}
32
+ {#if stepsInputArgs?.isArgManuallySet(id, key)}
33
33
  <button
34
34
  onclick={() => {
35
- testSteps?.evalArg(id, key, flowStateStore?.val, flowStore?.val, previewArgs?.val)
35
+ stepsInputArgs?.evalArg(id, key, flowStateStore?.val, flowStore?.val, previewArgs?.val)
36
36
  }}
37
37
  title="Re-evaluate input"
38
38
  class="-my-1 ml-0.5 hover:text-primary dark:hover:text-primary dark:text-gray-500 text-gray-300"
@@ -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
  }