windmill-components 1.504.6 → 1.510.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 (196) hide show
  1. package/package/ata/index.js +1 -1
  2. package/package/components/AppConnectInner.svelte +161 -29
  3. package/package/components/ArgInput.svelte +33 -103
  4. package/package/components/AuthSettings.svelte +45 -1
  5. package/package/components/Dev.svelte +31 -24
  6. package/package/components/DisplayResult.svelte +53 -26
  7. package/package/components/DisplayResult.svelte.d.ts +1 -1
  8. package/package/components/DynSelect.svelte +3 -3
  9. package/package/components/Editor.svelte +7 -4
  10. package/package/components/EditorBar.svelte +2 -2
  11. package/package/components/ErrorOrRecoveryHandler.svelte +73 -67
  12. package/package/components/ErrorOrRecoveryHandler.svelte.d.ts +8 -24
  13. package/package/components/FlowBuilder.svelte +11 -2
  14. package/package/components/FlowJobResult.svelte +12 -17
  15. package/package/components/FlowJobResult.svelte.d.ts +5 -18
  16. package/package/components/FlowPreviewContent.svelte +13 -10
  17. package/package/components/FlowPreviewContent.svelte.d.ts +1 -1
  18. package/package/components/FlowPreviewResult.svelte +14 -6
  19. package/package/components/FlowStatusViewer.svelte +11 -24
  20. package/package/components/FlowStatusViewer.svelte.d.ts +19 -18
  21. package/package/components/FlowStatusViewerInner.svelte +110 -131
  22. package/package/components/FlowStatusViewerInner.svelte.d.ts +20 -18
  23. package/package/components/GitDiffPreview.svelte +55 -0
  24. package/package/components/GitDiffPreview.svelte.d.ts +13 -0
  25. package/package/components/HistoricInputs.svelte +2 -2
  26. package/package/components/InitGitRepoPopover.svelte +410 -0
  27. package/package/components/InitGitRepoPopover.svelte.d.ts +13 -0
  28. package/package/components/InstanceSetting.svelte +21 -9
  29. package/package/components/InstanceSettings.svelte +16 -3
  30. package/package/components/JobLoader.svelte +567 -0
  31. package/package/components/JobLoader.svelte.d.ts +53 -0
  32. package/package/components/JobLogs.svelte +6 -4
  33. package/package/components/JobLogs.svelte.d.ts +5 -18
  34. package/package/components/LightweightResourcePicker.svelte +18 -39
  35. package/package/components/LightweightResourcePicker.svelte.d.ts +6 -22
  36. package/package/components/LogViewer.svelte +35 -41
  37. package/package/components/LogViewer.svelte.d.ts +6 -20
  38. package/package/components/ModulePreviewResultViewer.svelte +3 -1
  39. package/package/components/ModulePreviewResultViewer.svelte.d.ts +1 -0
  40. package/package/components/ModuleTest.svelte +16 -11
  41. package/package/components/PullGitRepoPopover.svelte +355 -0
  42. package/package/components/PullGitRepoPopover.svelte.d.ts +18 -0
  43. package/package/components/S3FilePicker.svelte +5 -3
  44. package/package/components/SavedInputs.svelte +2 -2
  45. package/package/components/ScriptBuilder.svelte +4 -3
  46. package/package/components/ScriptEditor.svelte +34 -31
  47. package/package/components/ScriptEditor.svelte.d.ts +3 -3
  48. package/package/components/ServiceLogsInner.svelte +2 -1
  49. package/package/components/ServiceLogsInner.svelte.d.ts +1 -0
  50. package/package/components/UserSettings.svelte +1 -1
  51. package/package/components/WorkerTagSelect.svelte +32 -3
  52. package/package/components/apps/components/buttons/AppButton.svelte +7 -1
  53. package/package/components/apps/components/buttons/AppButton.svelte.d.ts +1 -0
  54. package/package/components/apps/components/display/AppCustomComponent.svelte +1 -1
  55. package/package/components/apps/components/display/AppDisplayComponentByJobId.svelte +16 -11
  56. package/package/components/apps/components/display/AppJobIdLogComponent.svelte +13 -10
  57. package/package/components/apps/components/display/AppMenu.svelte +5 -0
  58. package/package/components/apps/components/display/dbtable/AppDbExplorer.svelte +3 -3
  59. package/package/components/apps/components/display/dbtable/DeleteRow.svelte +3 -3
  60. package/package/components/apps/components/display/dbtable/InsertRowRunnable.svelte +3 -3
  61. package/package/components/apps/components/display/dbtable/UpdateCell.svelte +3 -3
  62. package/package/components/apps/components/display/table/AppAggridInfiniteTable.svelte +3 -3
  63. package/package/components/apps/components/helpers/RunnableComponent.svelte +65 -54
  64. package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +5 -5
  65. package/package/components/apps/components/inputs/AppUserResource.svelte +26 -8
  66. package/package/components/apps/editor/AppEditorHeader.svelte +11 -5
  67. package/package/components/apps/editor/AppJobsDrawer.svelte +5 -5
  68. package/package/components/apps/editor/RunnableJobPanel.svelte +4 -4
  69. package/package/components/apps/editor/component/components.d.ts +12 -0
  70. package/package/components/apps/editor/component/components.js +19 -7
  71. package/package/components/assets/AssetButtons.svelte +38 -0
  72. package/package/components/assets/AssetButtons.svelte.d.ts +15 -0
  73. package/package/components/assets/AssetsDropdownButton.svelte +60 -72
  74. package/package/components/assets/AssetsDropdownButton.svelte.d.ts +3 -4
  75. package/package/components/assets/AssetsUsageDrawer.svelte +10 -10
  76. package/package/components/assets/JobAssetsViewer.svelte +79 -0
  77. package/package/components/assets/JobAssetsViewer.svelte.d.ts +7 -0
  78. package/package/components/assets/README_DEV.md +0 -0
  79. package/package/components/assets/lib.d.ts +9 -1
  80. package/package/components/assets/lib.js +48 -7
  81. package/package/components/common/fileUpload/FileUpload.svelte +126 -84
  82. package/package/components/common/fileUpload/FileUpload.svelte.d.ts +13 -3
  83. package/package/components/common/fileUpload/S3ArgInput.svelte +111 -0
  84. package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +21 -0
  85. package/package/components/common/table/ScriptRow.svelte +3 -1
  86. package/package/components/copilot/autocomplete/Autocompletor.js +23 -5
  87. package/package/components/copilot/chat/AIChatDisplay.svelte +8 -0
  88. package/package/components/copilot/chat/AIChatManager.svelte.js +13 -8
  89. package/package/components/copilot/chat/flow/ModuleAcceptReject.svelte +5 -5
  90. package/package/components/copilot/chat/flow/core.d.ts +1 -1
  91. package/package/components/copilot/chat/flow/core.js +2 -38
  92. package/package/components/copilot/chat/navigator/apiTools.d.ts +8 -0
  93. package/package/components/copilot/chat/navigator/apiTools.js +95 -15
  94. package/package/components/copilot/chat/navigator/core.d.ts +1 -1
  95. package/package/components/copilot/chat/navigator/core.js +2 -1
  96. package/package/components/copilot/chat/script/core.d.ts +11 -2
  97. package/package/components/copilot/chat/script/core.js +135 -1
  98. package/package/components/copilot/chat/shared.d.ts +10 -0
  99. package/package/components/copilot/chat/shared.js +56 -0
  100. package/package/components/copilot/lib.d.ts +1 -0
  101. package/package/components/copilot/lib.js +27 -9
  102. package/package/components/custom_ui.d.ts +1 -0
  103. package/package/components/flows/FlowAssetsHandler.svelte +133 -0
  104. package/package/components/flows/FlowAssetsHandler.svelte.d.ts +14 -0
  105. package/package/components/flows/content/FlowModuleComponent.svelte +16 -18
  106. package/package/components/flows/flowStore.d.ts +1 -1
  107. package/package/components/flows/map/FlowModuleSchemaItem.svelte +1 -0
  108. package/package/components/flows/propPicker/OutputPicker.svelte +9 -4
  109. package/package/components/flows/scheduleUtils.js +1 -1
  110. package/package/components/flows/types.d.ts +2 -1
  111. package/package/components/graph/FlowGraphV2.svelte +8 -104
  112. package/package/components/graph/FlowGraphV2.svelte.d.ts +0 -2
  113. package/package/components/graph/graphBuilder.svelte.d.ts +6 -3
  114. package/package/components/graph/graphBuilder.svelte.js +35 -9
  115. package/package/components/graph/renderers/edges/BaseEdge.svelte +2 -5
  116. package/package/components/graph/renderers/edges/BaseEdge.svelte.d.ts +1 -0
  117. package/package/components/graph/renderers/nodes/AssetNode.svelte +23 -20
  118. package/package/components/graph/renderers/nodes/AssetNode.svelte.d.ts +5 -10
  119. package/package/components/graph/renderers/nodes/AssetsOverflowedNode.svelte +1 -1
  120. package/package/components/graph/util.js +1 -1
  121. package/package/components/home/ItemsList.svelte +2 -0
  122. package/package/components/icons/AssetGenericIcon.svelte +0 -3
  123. package/package/components/jobs/JobPreview.svelte +10 -6
  124. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +13 -12
  125. package/package/components/runs/BatchReRunOptionsPane.svelte +5 -1
  126. package/package/components/runs/JobPreview.svelte +26 -16
  127. package/package/components/runs/{JobLoader.svelte.d.ts → JobsLoader.svelte.d.ts} +3 -3
  128. package/package/components/runs/NoWorkerWithTagWarning.svelte +2 -2
  129. package/package/components/runs/NoWorkerWithTagWarning.svelte.d.ts +1 -0
  130. package/package/components/runs/RunsFilter.svelte.d.ts +1 -1
  131. package/package/components/scriptEditor/LogPanel.svelte +3 -2
  132. package/package/components/script_builder.d.ts +2 -2
  133. package/package/components/settings/CreateToken.svelte +76 -41
  134. package/package/components/settings/CreateToken.svelte.d.ts +1 -1
  135. package/package/components/settings/ScopeSelector.svelte +613 -0
  136. package/package/components/settings/ScopeSelector.svelte.d.ts +8 -0
  137. package/package/components/settings/TokenDisplay.svelte +103 -0
  138. package/package/components/settings/TokenDisplay.svelte.d.ts +10 -0
  139. package/package/components/settings/TokensTable.svelte +70 -349
  140. package/package/components/sidebar/CriticalAlertModal.svelte +3 -0
  141. package/package/components/triggers/DeleteTriggerButton.svelte +1 -1
  142. package/package/components/triggers/TriggerEditorToolbar.svelte +3 -3
  143. package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte +55 -0
  144. package/package/components/triggers/TriggerRetriesAndErrorHandler.svelte.d.ts +13 -0
  145. package/package/components/triggers/TriggersEditor.svelte +45 -3
  146. package/package/components/triggers/TriggersWrapper.svelte +2 -2
  147. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +43 -2
  148. package/package/components/triggers/gcp/utils.js +9 -1
  149. package/package/components/triggers/http/OpenAPISpecGenerator.svelte +1 -0
  150. package/package/components/triggers/http/RouteEditorInner.svelte +208 -164
  151. package/package/components/triggers/http/RouteEditorInner.svelte.d.ts +6 -2
  152. package/package/components/triggers/http/utils.js +9 -3
  153. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +43 -2
  154. package/package/components/triggers/kafka/utils.js +9 -1
  155. package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte +4 -132
  156. package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte.d.ts +2 -5
  157. package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +178 -9
  158. package/package/components/triggers/mqtt/utils.js +9 -1
  159. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +43 -2
  160. package/package/components/triggers/nats/utils.js +9 -1
  161. package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +41 -2
  162. package/package/components/triggers/postgres/utils.js +9 -1
  163. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +34 -88
  164. package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +43 -2
  165. package/package/components/triggers/sqs/utils.js +9 -1
  166. package/package/components/triggers/utils.js +12 -0
  167. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +43 -2
  168. package/package/components/triggers/websocket/utils.js +11 -1
  169. package/package/components/workspaceSettings/AISettings.svelte +0 -2
  170. package/package/components/workspaceSettings/FilterList.svelte +56 -0
  171. package/package/components/workspaceSettings/FilterList.svelte.d.ts +8 -0
  172. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte +785 -0
  173. package/package/components/workspaceSettings/GitSyncFilterSettings.svelte.d.ts +18 -0
  174. package/package/gen/core/OpenAPI.js +1 -1
  175. package/package/gen/schemas.gen.d.ts +305 -23
  176. package/package/gen/schemas.gen.js +305 -23
  177. package/package/gen/services.gen.d.ts +33 -1
  178. package/package/gen/services.gen.js +66 -2
  179. package/package/gen/types.gen.d.ts +216 -11
  180. package/package/history.svelte.js +0 -2
  181. package/package/hub.d.ts +1 -0
  182. package/package/hubPaths.json +5 -2
  183. package/package/infer.js +16 -10
  184. package/package/svelte5Utils.svelte.d.ts +1 -0
  185. package/package/svelte5Utils.svelte.js +25 -18
  186. package/package/toast.js +10 -0
  187. package/package/utils.d.ts +3 -2
  188. package/package/utils.js +20 -5
  189. package/package.json +11 -11
  190. package/package/components/ResultJobLoader.svelte +0 -219
  191. package/package/components/ResultJobLoader.svelte.d.ts +0 -52
  192. package/package/components/TestJobLoader.svelte +0 -274
  193. package/package/components/TestJobLoader.svelte.d.ts +0 -43
  194. package/package/components/icons/AssetVarIcon.svelte +0 -31
  195. package/package/components/icons/AssetVarIcon.svelte.d.ts +0 -9
  196. /package/package/components/runs/{JobLoader.svelte → JobsLoader.svelte} +0 -0
@@ -5,8 +5,6 @@ export function formatAsset(asset) {
5
5
  return `res://${asset.path}`;
6
6
  case 's3object':
7
7
  return `s3://${asset.path}`;
8
- case 'variable':
9
- return `var://${asset.path}`;
10
8
  }
11
9
  }
12
10
  export function getAssetUsagePageUri(usage) {
@@ -22,6 +20,11 @@ export function assetEq(a, b) {
22
20
  return a === b;
23
21
  return a.kind === b.kind && a.path === b.path;
24
22
  }
23
+ export function assetsEq(a, b) {
24
+ if (a.length !== b.length)
25
+ return false;
26
+ return a.every((asset, index) => assetEq(asset, b[index]));
27
+ }
25
28
  export function parseAssetFromString(s) {
26
29
  if (s.startsWith('res://')) {
27
30
  return { kind: 'resource', path: s.slice(6) };
@@ -32,9 +35,6 @@ export function parseAssetFromString(s) {
32
35
  else if (s.startsWith('s3://')) {
33
36
  return { kind: 's3object', path: s.slice(5) };
34
37
  }
35
- else if (s.startsWith('var://')) {
36
- return { kind: 'variable', path: s.slice(6) };
37
- }
38
38
  return undefined;
39
39
  }
40
40
  export function formatAssetKind(asset) {
@@ -54,7 +54,48 @@ export function formatAssetKind(asset) {
54
54
  }
55
55
  case 's3object':
56
56
  return 'S3 Object';
57
- case 'variable':
58
- return 'Variable';
59
57
  }
60
58
  }
59
+ export function formatAssetAccessType(accessType) {
60
+ switch (accessType) {
61
+ case 'r':
62
+ return 'Read';
63
+ case 'w':
64
+ return 'Write';
65
+ case 'rw':
66
+ return 'R/W';
67
+ }
68
+ return '?';
69
+ }
70
+ export function getAccessType(asset) {
71
+ if (asset.alt_access_type)
72
+ return asset.alt_access_type;
73
+ if (asset.access_type)
74
+ return asset.access_type;
75
+ }
76
+ export function getFlowModuleAssets(flowModuleValue, additionalAssetsMap) {
77
+ if (flowModuleValue.value.type === 'rawscript')
78
+ return flowModuleValue.value.assets;
79
+ if (flowModuleValue.value.type === 'script' || flowModuleValue.value.type === 'flow') {
80
+ const additionalAssets = additionalAssetsMap?.[flowModuleValue.id];
81
+ if (additionalAssets)
82
+ return additionalAssets;
83
+ }
84
+ return undefined;
85
+ }
86
+ export function parseInputArgsAssets(args) {
87
+ const arr = [];
88
+ for (const v of Object.values(args)) {
89
+ if (typeof v === 'string') {
90
+ const asset = parseAssetFromString(v);
91
+ if (asset)
92
+ arr.push(asset);
93
+ }
94
+ else if (v && typeof v === 'object' && typeof v['s3'] === 'string') {
95
+ const s3 = v['s3'];
96
+ const storage = typeof v['storage'] == 'string' ? v['storage'] : undefined;
97
+ arr.push({ kind: 's3object', path: `${storage ?? ''}/${s3}` });
98
+ }
99
+ }
100
+ return arr;
101
+ }
@@ -5,15 +5,17 @@ import { sendUserToast } from '../../../toast';
5
5
  import { workspaceStore } from '../../../stores';
6
6
  import { AppService, HelpersService } from '../../../gen';
7
7
  import { writable } from 'svelte/store';
8
- import { Ban, CheckCheck, FileWarning, Files, RefreshCcw, Trash } from 'lucide-svelte';
8
+ import { Ban, CheckCheck, FileWarning, Files, RefreshCcw, Trash, XIcon } from 'lucide-svelte';
9
9
  import { twMerge } from 'tailwind-merge';
10
10
  import { createEventDispatcher, onDestroy } from 'svelte';
11
11
  import { emptyString } from '../../../utils';
12
- let { acceptedFileTypes = ['*'], allowMultiple = true, allowDelete = true, folderOnly = false, containerText = folderOnly
13
- ? 'Drag and drop a folder here or click to browse'
14
- : allowMultiple
15
- ? 'Drag and drop files here or click to browse'
16
- : 'Drag and drop a file here or click to browse', customResourcePath = undefined, customResourceType = undefined, customClass = '', customStyle = '', randomFileKey = false, pathTransformer = undefined, forceDisplayUploads = $bindable(false), defaultValue = undefined, workspace = undefined, fileUploads = writable([]), appPath = undefined, disabled = false, iconSize = undefined, initialValue = undefined, computeForceViewerPolicies = undefined } = $props();
12
+ let { acceptedFileTypes = ['*'], allowMultiple = true, allowDelete = true, folderOnly = false, containerText: customContainerText = undefined, customResourcePath = undefined, customResourceType = undefined, customClass = '', customStyle = '', randomFileKey = false, pathTransformer = undefined, forceDisplayUploads = $bindable(false), defaultValue = undefined, workspace = undefined, fileUploads = writable([]), appPath = undefined, disabled = false, iconSize = undefined, initialValue = undefined, computeForceViewerPolicies = undefined } = $props();
13
+ const containerText = $derived(customContainerText ??
14
+ (folderOnly
15
+ ? 'Drag and drop a folder here or click to browse'
16
+ : allowMultiple
17
+ ? 'Drag and drop files here or click to browse'
18
+ : 'Drag and drop a file here or click to browse'));
17
19
  const dispatch = createEventDispatcher();
18
20
  let initialS3 = $derived(Array.isArray(initialValue)
19
21
  ? initialValue?.map((v) => v.s3)
@@ -21,16 +23,15 @@ let initialS3 = $derived(Array.isArray(initialValue)
21
23
  ? [initialValue?.s3]
22
24
  : undefined);
23
25
  init();
26
+ function transform(initialValue) {
27
+ return {
28
+ name: initialValue?.filename ?? initialValue?.s3 ?? 'Unknown file',
29
+ path: initialValue?.s3,
30
+ fromBucket: true
31
+ };
32
+ }
24
33
  function init() {
25
34
  if (initialS3) {
26
- function transform(initialValue) {
27
- return {
28
- name: initialValue.filename,
29
- size: 0,
30
- progress: 100,
31
- path: initialValue?.s3
32
- };
33
- }
34
35
  for (const s3 of initialS3) {
35
36
  if (!$fileUploads.find((fileUpload) => fileUpload.path === s3)) {
36
37
  let initialFileUploads = initialValue
@@ -43,6 +44,12 @@ function init() {
43
44
  }
44
45
  }
45
46
  }
47
+ export function addUpload(upload) {
48
+ $fileUploads = [...$fileUploads, transform(upload)];
49
+ }
50
+ export function setUpload(upload) {
51
+ $fileUploads = [transform(upload)];
52
+ }
46
53
  async function handleChange(files) {
47
54
  if (folderOnly) {
48
55
  uniqueFolderPrefix = getRandomFolderPrefix();
@@ -278,8 +285,28 @@ onDestroy(() => {
278
285
  });
279
286
  </script>
280
287
 
288
+ {#snippet fileInput()}
289
+ <FileInput
290
+ {folderOnly}
291
+ {disabled}
292
+ accept={acceptedFileTypes?.join(',')}
293
+ multiple={allowMultiple}
294
+ returnFileNames
295
+ {iconSize}
296
+ on:change={({ detail }) => {
297
+ forceDisplayUploads = false
298
+ handleChange(detail)
299
+ }}
300
+ class={twMerge('w-full h-full', customClass, 'wm-file-input')}
301
+ style={customStyle}
302
+ defaultFile={defaultValue}
303
+ >
304
+ {containerText}{#if disabled}<br />(Disabled){/if}
305
+ </FileInput>
306
+ {/snippet}
307
+
281
308
  <div class="w-full h-full p-0 flex flex-col">
282
- {#if $fileUploads.length > 0 && !forceDisplayUploads}
309
+ {#if $fileUploads.length > 0}
283
310
  <div class="border rounded-md flex flex-col gap-1 divide-y h-full w-full p-1">
284
311
  <div class="flex h-full overflow-y-auto flex-col">
285
312
  {#each $fileUploads as fileUpload}
@@ -352,7 +379,7 @@ onDestroy(() => {
352
379
  Remove from list
353
380
  </Button>
354
381
  {/if}
355
- {#if fileUpload.progress < 100 && !fileUpload.cancelled && !fileUpload.errorMessage}
382
+ {#if fileUpload.progress !== undefined && fileUpload.progress < 100 && !fileUpload.cancelled && !fileUpload.errorMessage}
356
383
  <Button
357
384
  size="xs2"
358
385
  color="light"
@@ -390,100 +417,115 @@ onDestroy(() => {
390
417
  >
391
418
  Delete
392
419
  </Button>
420
+ {:else if fileUpload.fromBucket}
421
+ <Button
422
+ size="xs2"
423
+ color="red"
424
+ variant="border"
425
+ on:click={() => {
426
+ $fileUploads = $fileUploads.filter(
427
+ (_fileUpload) => _fileUpload.name !== fileUpload.name
428
+ )
429
+
430
+ if (fileUpload.path) {
431
+ dispatch('deletion', { path: fileUpload.path })
432
+ }
433
+ }}
434
+ startIcon={{
435
+ icon: XIcon
436
+ }}
437
+ >
438
+ Remove
439
+ </Button>
393
440
  {/if}
394
441
  </div>
395
442
  </div>
396
- <FileProgressBar
397
- progress={fileUpload.progress}
398
- color={fileUpload.errorMessage
399
- ? '#ef4444'
400
- : fileUpload.cancelled
401
- ? '#eab308'
402
- : fileUpload.progress === 100
403
- ? '#22c55e'
404
- : '#3b82f6'}
405
- ended={fileUpload.cancelled || fileUpload.errorMessage !== undefined}
406
- >
407
- {#if fileUpload.errorMessage}
408
- <span class="text-xs text-red-600">{fileUpload.errorMessage}</span>
409
- {:else if fileUpload.cancelled}
410
- <span class="text-xs text-yellow-600">Upload cancelled</span>
411
- {/if}
412
- </FileProgressBar>
443
+ {#if !fileUpload.fromBucket}
444
+ <FileProgressBar
445
+ progress={fileUpload.progress}
446
+ color={fileUpload.errorMessage
447
+ ? '#ef4444'
448
+ : fileUpload.cancelled
449
+ ? '#eab308'
450
+ : fileUpload.progress === 100
451
+ ? '#22c55e'
452
+ : '#3b82f6'}
453
+ ended={fileUpload.cancelled || fileUpload.errorMessage !== undefined}
454
+ >
455
+ {#if fileUpload.errorMessage}
456
+ <span class="text-xs text-red-600">{fileUpload.errorMessage}</span>
457
+ {:else if fileUpload.cancelled}
458
+ <span class="text-xs text-yellow-600">Upload cancelled</span>
459
+ {/if}
460
+ </FileProgressBar>
461
+ {/if}
413
462
  {#if !(fileUpload.cancelled || fileUpload.errorMessage !== undefined)}
414
463
  <span class="text-xs text-gray-500 dark:text-gray-200">
415
- {fileUpload.progress === 100 ? 'Upload finished' : `Uploading`} to path: {fileUpload.path ??
416
- 'N/A'}
464
+ {#if fileUpload.fromBucket}
465
+ {fileUpload.path ?? 'N/A'}
466
+ {:else}
467
+ {fileUpload.progress === 100 ? 'Upload finished' : `Uploading`} to path: {fileUpload.path ??
468
+ 'N/A'}
469
+ {/if}
417
470
  </span>
418
471
  {/if}
419
472
  </div>
420
473
  {/each}
421
474
  </div>
422
- {#if allowMultiple}
423
- <div class="flex flex-row gap-1 items-center justify-end p-1">
424
- {#if !$fileUploads.every((fileUpload) => fileUpload.progress === 100 || fileUpload.cancelled)}
475
+ <div class="flex flex-row gap-1 items-center justify-end p-1">
476
+ {#if !forceDisplayUploads && (allowMultiple || folderOnly) && !$fileUploads.every((fileUpload) => fileUpload.progress === 100 || fileUpload.cancelled || fileUpload.fromBucket)}
477
+ <Button
478
+ size="xs2"
479
+ color="light"
480
+ on:click={() => {
481
+ $fileUploads = $fileUploads.map((fileUpload) => {
482
+ if (fileUpload.progress === 100 || fileUpload.cancelled) {
483
+ return fileUpload
484
+ }
485
+
486
+ fileUpload.cancelled = true
487
+ fileUpload.progress = 0
488
+ return fileUpload
489
+ })
490
+ }}
491
+ startIcon={{
492
+ icon: Ban
493
+ }}
494
+ >
495
+ Cancel all uploads
496
+ </Button>
497
+ {/if}
498
+ {#if allowMultiple}
499
+ {#if forceDisplayUploads}
500
+ {@render fileInput()}
501
+ {:else}
425
502
  <Button
426
503
  size="xs2"
427
504
  color="light"
428
505
  on:click={() => {
429
- $fileUploads = $fileUploads.map((fileUpload) => {
430
- if (fileUpload.progress === 100 || fileUpload.cancelled) {
431
- return fileUpload
432
- }
433
-
434
- fileUpload.cancelled = true
435
- fileUpload.progress = 0
436
- return fileUpload
437
- })
506
+ forceDisplayUploads = true
438
507
  }}
439
508
  startIcon={{
440
- icon: Ban
509
+ icon: Files
441
510
  }}
511
+ disabled={$fileUploads.some(
512
+ (fileUpload) =>
513
+ fileUpload.progress !== 100 && !fileUpload.cancelled && !fileUpload.fromBucket
514
+ )}
442
515
  >
443
- Cancel all uploads
516
+ Upload more files
444
517
  </Button>
445
518
  {/if}
446
- <Button
447
- size="xs2"
448
- color="light"
449
- on:click={() => {
450
- forceDisplayUploads = true
451
- }}
452
- startIcon={{
453
- icon: Files
454
- }}
455
- disabled={$fileUploads.some(
456
- (fileUpload) => fileUpload.progress !== 100 && !fileUpload.cancelled
457
- )}
458
- >
459
- Upload more files
460
- </Button>
461
- </div>
462
- {/if}
519
+ {/if}
520
+ </div>
463
521
  </div>
464
522
  {:else}
465
- <FileInput
466
- {folderOnly}
467
- {disabled}
468
- accept={acceptedFileTypes?.join(',')}
469
- multiple={allowMultiple}
470
- returnFileNames
471
- {iconSize}
472
- on:change={({ detail }) => {
473
- forceDisplayUploads = false
474
- handleChange(detail)
475
- }}
476
- class={twMerge('w-full h-full', customClass, 'wm-file-input')}
477
- style={customStyle}
478
- defaultFile={defaultValue}
479
- >
480
- {containerText}{#if disabled}<br />(Disabled){/if}
481
- </FileInput>
523
+ {@render fileInput()}
482
524
  {/if}
483
525
  {#if initialS3 && initialS3.length > 0 && $fileUploads.length == 0}
484
526
  <div class="flex flex-row gap-1 items-center p-1">
485
527
  <span class="text-sm">
486
- File currently selected: {initialS3?.join(', ')}
528
+ File{initialS3.length > 1 ? 's' : ''} currently selected: {initialS3?.join(', ')}
487
529
  </span>
488
530
  </div>
489
531
  {/if}
@@ -1,13 +1,14 @@
1
1
  import { type Writable } from 'svelte/store';
2
2
  type FileUploadData = {
3
3
  name: string;
4
- size: number;
5
- progress: number;
4
+ size?: number;
5
+ progress?: number;
6
6
  cancelled?: boolean;
7
7
  errorMessage?: string;
8
8
  path?: string;
9
9
  file?: File;
10
10
  deleteToken?: string;
11
+ fromBucket?: boolean;
11
12
  };
12
13
  interface Props {
13
14
  acceptedFileTypes?: string[] | undefined;
@@ -65,6 +66,15 @@ declare const FileUpload: $$__sveltets_2_IsomorphicComponent<Props, {
65
66
  }>;
66
67
  } & {
67
68
  [evt: string]: CustomEvent<any>;
68
- }, {}, {}, "forceDisplayUploads">;
69
+ }, {}, {
70
+ addUpload: (upload: {
71
+ s3: string;
72
+ filename?: string;
73
+ }) => void;
74
+ setUpload: (upload: {
75
+ s3: string;
76
+ filename?: string;
77
+ }) => void;
78
+ }, "forceDisplayUploads">;
69
79
  type FileUpload = InstanceType<typeof FileUpload>;
70
80
  export default FileUpload;
@@ -0,0 +1,111 @@
1
+ <script lang="ts">import S3FilePicker from '../../S3FilePicker.svelte';
2
+ import Toggle from '../../Toggle.svelte';
3
+ import { Loader2, Pipette } from 'lucide-svelte';
4
+ import FileUpload from './FileUpload.svelte';
5
+ import Button from '../button/Button.svelte';
6
+ import { userStore } from '../../../stores';
7
+ let { multiple, value = $bindable(), defaultValue, setNewValueFromCode, onFocus, onBlur, computeS3ForceViewerPolicies, workspace, editor = $bindable(), appPath } = $props();
8
+ let s3FileUploadRawMode = $state(false);
9
+ let s3FilePicker = $state(undefined);
10
+ let fileUpload = $state(undefined);
11
+ </script>
12
+
13
+ {#if $userStore}
14
+ <S3FilePicker
15
+ bind:this={s3FilePicker}
16
+ on:selectAndClose={(ev) => {
17
+ if (multiple) {
18
+ if (Array.isArray(value)) {
19
+ value.push(ev.detail)
20
+ } else {
21
+ value = [ev.detail]
22
+ }
23
+ fileUpload?.addUpload(ev.detail)
24
+ } else {
25
+ value = ev.detail
26
+ fileUpload?.setUpload(value)
27
+ }
28
+ editor?.setCode(JSON.stringify(value))
29
+ }}
30
+ readOnlyMode={false}
31
+ />
32
+ {/if}
33
+
34
+ <div class="flex flex-col w-full gap-1">
35
+ <Toggle
36
+ class="flex justify-end"
37
+ bind:checked={s3FileUploadRawMode}
38
+ size="xs"
39
+ options={{ left: `Raw S3 object${multiple ? 's' : ''} input` }}
40
+ />
41
+ {#if s3FileUploadRawMode}
42
+ {#await import('../../JsonEditor.svelte')}
43
+ <Loader2 class="animate-spin" />
44
+ {:then Module}
45
+ <Module.default
46
+ bind:editor
47
+ on:focus={(e) => {
48
+ onFocus()
49
+ }}
50
+ on:blur={(e) => {
51
+ onBlur()
52
+ }}
53
+ code={JSON.stringify(value ?? defaultValue ?? (multiple ? [] : { s3: '' }), null, 2)}
54
+ on:changeValue={(e) => {
55
+ setNewValueFromCode(e.detail)
56
+ }}
57
+ />
58
+ {/await}
59
+ {:else}
60
+ <FileUpload
61
+ bind:this={fileUpload}
62
+ {appPath}
63
+ computeForceViewerPolicies={computeS3ForceViewerPolicies}
64
+ {workspace}
65
+ allowMultiple={multiple}
66
+ randomFileKey={true}
67
+ on:addition={(evt) => {
68
+ const s3Object = {
69
+ s3: evt.detail?.path ?? '',
70
+ filename: evt.detail?.filename ?? ''
71
+ }
72
+ if (multiple) {
73
+ if (Array.isArray(value)) {
74
+ value.push(s3Object)
75
+ } else {
76
+ value = [s3Object]
77
+ }
78
+ } else {
79
+ value = s3Object
80
+ }
81
+ }}
82
+ on:deletion={(evt) => {
83
+ if (multiple) {
84
+ if (Array.isArray(value)) {
85
+ value = value.filter((v) => v.s3 !== evt.detail?.path)
86
+ }
87
+ } else {
88
+ value = {
89
+ s3: ''
90
+ }
91
+ }
92
+ }}
93
+ defaultValue={multiple ? defaultValue?.map((v) => v.s3) : defaultValue?.s3}
94
+ initialValue={value}
95
+ />
96
+ {/if}
97
+ {#if $userStore}
98
+ <Button
99
+ variant="border"
100
+ color="light"
101
+ size="xs"
102
+ btnClasses="mt-1"
103
+ on:click={() => {
104
+ s3FilePicker?.open?.(value)
105
+ }}
106
+ startIcon={{ icon: Pipette }}
107
+ >
108
+ {multiple ? 'Add' : 'Choose'} an object from the catalog
109
+ </Button>
110
+ {/if}
111
+ </div>
@@ -0,0 +1,21 @@
1
+ import type SimpleEditor from '../../SimpleEditor.svelte';
2
+ type $$ComponentProps = {
3
+ multiple: boolean;
4
+ value: any;
5
+ defaultValue: any;
6
+ setNewValueFromCode: (v: any) => void;
7
+ onFocus: () => void;
8
+ onBlur: () => void;
9
+ computeS3ForceViewerPolicies: (() => {
10
+ allowed_resources: string[];
11
+ allow_user_resources: boolean;
12
+ allow_workspace_resource: boolean;
13
+ file_key_regex: string;
14
+ } | undefined) | undefined;
15
+ workspace: string | undefined;
16
+ editor: SimpleEditor | undefined;
17
+ appPath: string | undefined;
18
+ };
19
+ declare const S3ArgInput: import("svelte").Component<$$ComponentProps, {}, "value" | "editor">;
20
+ type S3ArgInput = ReturnType<typeof S3ArgInput>;
21
+ export default S3ArgInput;
@@ -84,7 +84,9 @@ let versionsDrawerOpen = $state(false);
84
84
  <NoMainFuncBadge />
85
85
  {/if}
86
86
  {#if script.kind !== 'script'}
87
- <Badge color="blue" baseClass="border">{capitalize(script.kind)}</Badge>
87
+ <Badge color="blue" baseClass="border"
88
+ >{script.kind === 'failure' ? 'Error handler' : capitalize(script.kind)}</Badge
89
+ >
88
90
  {/if}
89
91
  <SharedBadge canWrite={script.canWrite} extraPerms={script.extra_perms} />
90
92
  <DraftBadge has_draft={script.has_draft} draft_only={script.draft_only} />
@@ -3,13 +3,21 @@ import { Position, languages } from 'monaco-editor';
3
3
  import { LRUCache } from 'lru-cache';
4
4
  import { autocompleteRequest } from './request';
5
5
  import { FIM_MAX_TOKENS } from '../lib';
6
- function filterCompletion(completion, suffix) {
6
+ function filterCompletion(completion, suffix, shouldReturnMultiline) {
7
7
  const trimmedCompletion = completion.replaceAll('\n', '');
8
8
  const trimmedSuffix = suffix.slice(0, FIM_MAX_TOKENS).replaceAll('\n', '');
9
9
  if (trimmedSuffix.startsWith(trimmedCompletion)) {
10
- console.log('suffix starts with completion', suffix, completion);
11
10
  return;
12
11
  }
12
+ if (!shouldReturnMultiline) {
13
+ if (completion.startsWith('\n')) {
14
+ // TODO improve cache for this case so that we can use cache when accepting the first line of a multiline completion which starts with \n
15
+ return completion.split('\n').slice(0, 2).join('\n');
16
+ }
17
+ else {
18
+ return completion.split('\n').slice(0, 1).join('\n');
19
+ }
20
+ }
13
21
  return completion;
14
22
  }
15
23
  export class Autocompletor {
@@ -29,9 +37,10 @@ export class Autocompletor {
29
37
  model.uri.toString() !== editor.getModel()?.uri.toString()) {
30
38
  return { items: [] };
31
39
  }
40
+ const shouldReturnMultiline = this.#shouldReturnMultiline(model, position);
32
41
  const result = await this.#autocomplete(model, position);
33
42
  if (result) {
34
- const completion = filterCompletion(result.completion, result.suffix);
43
+ const completion = filterCompletion(result.completion, result.suffix, shouldReturnMultiline);
35
44
  if (!completion) {
36
45
  return { items: [] };
37
46
  }
@@ -82,6 +91,17 @@ export class Autocompletor {
82
91
  this.#completionDisposable.dispose();
83
92
  this.#cursorDisposable.dispose();
84
93
  }
94
+ #shouldReturnMultiline(model, position) {
95
+ if (position.column === model.getLineMaxColumn(position.lineNumber)) {
96
+ const cachedCompletion = this.#cache.get(position.lineNumber);
97
+ if (cachedCompletion) {
98
+ const firstCachedLine = cachedCompletion.linePrefix + cachedCompletion.completion.split('\n')[0];
99
+ const lineContent = model.getLineContent(position.lineNumber);
100
+ return firstCachedLine === lineContent;
101
+ }
102
+ }
103
+ return false;
104
+ }
85
105
  async #autocomplete(model, position) {
86
106
  const thisTs = Date.now();
87
107
  this.#lastTs = thisTs;
@@ -112,13 +132,11 @@ export class Autocompletor {
112
132
  const newLinePrefix = completeLine.substring(0, position.column - 1);
113
133
  if (newLinePrefix === linePrefix) {
114
134
  const modifiedCompletion = cachedCompletion.completion.slice(position.column - cachedCompletion.column);
115
- console.debug('autocomplete partial cache hit', modifiedCompletion);
116
135
  return { completion: modifiedCompletion, suffix };
117
136
  }
118
137
  }
119
138
  else if (position.column === cachedCompletion.column &&
120
139
  cachedCompletion.linePrefix === linePrefix) {
121
- console.debug('autocomplete exact cache hit', cachedCompletion.completion);
122
140
  return { completion: cachedCompletion.completion, suffix };
123
141
  }
124
142
  }
@@ -10,6 +10,7 @@ import ChatMode from './ChatMode.svelte';
10
10
  import Markdown from 'svelte-exmarkdown';
11
11
  import { aiChatManager, AIMode } from './AIChatManager.svelte';
12
12
  import AIChatInput from './AIChatInput.svelte';
13
+ import { getModifierKey } from '../../../utils';
13
14
  let { messages, pastChats, hasDiff, diffMode = false, // todo: remove default
14
15
  selectedContext = $bindable([]), // todo: remove default
15
16
  availableContext = [], // todo: remove default
@@ -120,6 +121,13 @@ $effect(() => {
120
121
  {@render headerRight?.()}
121
122
  </div>
122
123
  </div>
124
+ {#if messages.length === 0}
125
+ <span class="text-2xs text-gray-500 dark:text-gray-400 text-center px-2 my-2"
126
+ >You can use {getModifierKey()}L to open or close this chat, and {getModifierKey()}K in the
127
+ script editor to modify selected lines.</span
128
+ >
129
+ {/if}
130
+
123
131
  {#if messages.length > 0}
124
132
  <div
125
133
  class="h-full overflow-y-scroll pt-2 pb-12"
@@ -59,16 +59,18 @@ class AIChatManager {
59
59
  ask: true
60
60
  });
61
61
  open = $derived(chatState.size > 0);
62
- constructor() {
63
- loadApiTools()
64
- .then((tools) => {
65
- this.apiTools = tools;
66
- })
67
- .catch((err) => {
62
+ loadApiTools = async () => {
63
+ try {
64
+ this.apiTools = await loadApiTools();
65
+ if (this.mode === AIMode.NAVIGATOR) {
66
+ this.tools = [this.changeModeTool, ...navigatorTools, ...this.apiTools];
67
+ }
68
+ }
69
+ catch (err) {
68
70
  console.error('Error loading api tools', err);
69
71
  this.apiTools = [];
70
- });
71
- }
72
+ }
73
+ };
72
74
  setAiChatInput(aiChatInput) {
73
75
  this.aiChatInput = aiChatInput;
74
76
  }
@@ -482,6 +484,9 @@ class AIChatManager {
482
484
  }
483
485
  }
484
486
  };
487
+ if (this.mode === AIMode.NAVIGATOR && this.apiTools.length === 0) {
488
+ await this.loadApiTools();
489
+ }
485
490
  await this.chatRequest({
486
491
  ...params
487
492
  });
@@ -1,8 +1,8 @@
1
- <script module>
2
- export const getAiModuleAction = (id: string | undefined) => {
3
- if (!id) return undefined
4
- return aiChatManager.flowAiChatHelpers?.getModuleAction(id)
5
- }
1
+ <script module lang="ts">export const getAiModuleAction = (id) => {
2
+ if (!id)
3
+ return undefined;
4
+ return aiChatManager.flowAiChatHelpers?.getModuleAction(id);
5
+ };
6
6
  </script>
7
7
 
8
8
  <script lang="ts">import { twMerge } from 'tailwind-merge';