windmill-components 1.687.0 → 1.695.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 (264) hide show
  1. package/package/components/ArgInput.svelte +2 -0
  2. package/package/components/AutoscalingConfigEditor.svelte +18 -4
  3. package/package/components/CompareWorkspaces.svelte +206 -157
  4. package/package/components/DatatableSchemaDiff.svelte +2 -2
  5. package/package/components/Dev.svelte +401 -85
  6. package/package/components/EditableSchemaForm.svelte +4 -0
  7. package/package/components/ErrorOrRecoveryHandler.svelte +2 -2
  8. package/package/components/FlowPreviewContent.svelte +32 -30
  9. package/package/components/FlowRestartButton.svelte +143 -61
  10. package/package/components/FlowRestartButton.svelte.d.ts +37 -0
  11. package/package/components/FlowStatusViewer.svelte +15 -1
  12. package/package/components/FlowStatusViewer.svelte.d.ts +10 -2
  13. package/package/components/FlowStatusViewerInner.svelte +1 -2
  14. package/package/components/FlowStatusViewerInner.svelte.d.ts +6 -2
  15. package/package/components/ForkConflictModal.svelte +57 -0
  16. package/package/components/ForkConflictModal.svelte.d.ts +3 -0
  17. package/package/components/GitRepoViewer.svelte +251 -97
  18. package/package/components/InputTransformSchemaForm.svelte +1 -1
  19. package/package/components/InstanceSettings.svelte +36 -16
  20. package/package/components/Login.svelte +113 -28
  21. package/package/components/Login.svelte.d.ts +1 -0
  22. package/package/components/Path.svelte +7 -1
  23. package/package/components/Path.svelte.d.ts +1 -1
  24. package/package/components/RunsPage.svelte +2 -1
  25. package/package/components/S3FilePickerInner.svelte +89 -89
  26. package/package/components/ScriptEditor.svelte +18 -5
  27. package/package/components/ShareModal.svelte.d.ts +1 -1
  28. package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +3 -0
  29. package/package/components/apps/components/helpers/executeRunnable.js +2 -1
  30. package/package/components/apps/editor/AppReportsDrawerInner.svelte +1 -1
  31. package/package/components/apps/editor/appPolicy.js +2 -1
  32. package/package/components/apps/editor/commonAppUtils.d.ts +3 -0
  33. package/package/components/apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte +1 -1
  34. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +7 -0
  35. package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte +49 -0
  36. package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte.d.ts +9 -0
  37. package/package/components/apps/inputType.d.ts +1 -0
  38. package/package/components/apps/sharedTypes.d.ts +1 -0
  39. package/package/components/auditLogs/AuditLogsFilters.svelte +8 -3
  40. package/package/components/common/fileUpload/S3ArgInput.svelte +12 -10
  41. package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +2 -0
  42. package/package/components/copilot/chat/AIChatDisplay.svelte +5 -36
  43. package/package/components/copilot/chat/AIChatInput.svelte +56 -47
  44. package/package/components/copilot/chat/AIChatManager.svelte.js +48 -46
  45. package/package/components/copilot/chat/ContextElementBadge.svelte +6 -4
  46. package/package/components/copilot/chat/app/core.d.ts +12 -20
  47. package/package/components/copilot/chat/app/core.js +103 -160
  48. package/package/components/copilot/chat/app/core.test.js +234 -9
  49. package/package/components/copilot/chat/context.js +44 -0
  50. package/package/components/copilot/chat/flow/FlowAIChat.svelte +5 -3
  51. package/package/components/copilot/chat/flow/core.d.ts +2 -1
  52. package/package/components/copilot/chat/flow/core.js +48 -21
  53. package/package/components/copilot/chat/flow/helperUtils.d.ts +5 -2
  54. package/package/components/copilot/chat/flow/helperUtils.js +33 -1
  55. package/package/components/copilot/chat/flow/helperUtils.test.js +116 -1
  56. package/package/components/copilot/chat/flow/openFlow.json +1 -1
  57. package/package/components/copilot/chat/flow/openFlowZod.gen.js +24 -0
  58. package/package/components/copilot/chat/script/core.js +3 -0
  59. package/package/components/copilot/chat/shared.d.ts +6 -0
  60. package/package/components/copilot/chat/shared.js +22 -1
  61. package/package/components/copilot/chat/shared.test.d.ts +1 -0
  62. package/package/components/copilot/chat/shared.test.js +412 -0
  63. package/package/components/copilot/chat/workspaceTools.d.ts +7 -0
  64. package/package/components/copilot/chat/workspaceTools.js +239 -0
  65. package/package/components/copilot/chat/workspaceToolsZod.gen.d.ts +1295 -0
  66. package/package/components/copilot/chat/workspaceToolsZod.gen.js +424 -0
  67. package/package/components/copilot/lib.js +3 -1
  68. package/package/components/copilot/lib.test.d.ts +1 -0
  69. package/package/components/copilot/lib.test.js +19 -0
  70. package/package/components/copilot/modelConfig.d.ts +3 -0
  71. package/package/components/copilot/modelConfig.js +10 -0
  72. package/package/components/flows/FlowProgressBar.svelte +5 -2
  73. package/package/components/flows/content/FlowModuleComponent.svelte +636 -599
  74. package/package/components/flows/conversations/FlowChatManager.svelte.js +21 -10
  75. package/package/components/flows/flowStateUtils.svelte.js +5 -1
  76. package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
  77. package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +1 -0
  78. package/package/components/git_sync/GitSyncContext.svelte.js +0 -2
  79. package/package/components/graph/FlowGraphV2.svelte +7 -3
  80. package/package/components/graph/FlowGraphV2.svelte.d.ts +1 -0
  81. package/package/components/graph/renderers/triggers/TriggersBadge.svelte +3 -0
  82. package/package/components/home/deploy_ui.js +1 -1
  83. package/package/components/icons/AzureIcon.svelte +12 -25
  84. package/package/components/icons/AzureIcon.svelte.d.ts +3 -2
  85. package/package/components/instanceSettings.js +24 -0
  86. package/package/components/mcp/McpScopeSelector.svelte +119 -9
  87. package/package/components/mcp/McpScopeSelector.svelte.d.ts +1 -0
  88. package/package/components/offboarding-utils.js +2 -0
  89. package/package/components/progressBar/ProgressBar.svelte +9 -5
  90. package/package/components/progressBar/ProgressBar.svelte.d.ts +1 -0
  91. package/package/components/raw_apps/DeleteAfterUsePopup.svelte +52 -0
  92. package/package/components/raw_apps/DeleteAfterUsePopup.svelte.d.ts +9 -0
  93. package/package/components/raw_apps/RawAppBackgroundRunner.svelte +5 -1
  94. package/package/components/raw_apps/RawAppEditor.svelte +159 -102
  95. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +9 -3
  96. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte.d.ts +2 -1
  97. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +1 -0
  98. package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte.d.ts +1 -0
  99. package/package/components/raw_apps/RawAppInputsSpecEditor.svelte +48 -5
  100. package/package/components/raw_apps/RawAppSharedUiDrawer.svelte +129 -0
  101. package/package/components/raw_apps/RawAppSharedUiDrawer.svelte.d.ts +5 -0
  102. package/package/components/raw_apps/RawAppSidebar.svelte +12 -0
  103. package/package/components/raw_apps/dataTableRefUtils.d.ts +7 -0
  104. package/package/components/raw_apps/dataTableRefUtils.js +34 -0
  105. package/package/components/raw_apps/dataTableRefUtils.test.d.ts +1 -0
  106. package/package/components/raw_apps/dataTableRefUtils.test.js +29 -0
  107. package/package/components/raw_apps/rawAppPolicy.d.ts +1 -0
  108. package/package/components/raw_apps/rawAppPolicy.js +17 -2
  109. package/package/components/resources/resourceTypesFilter.d.ts +19 -0
  110. package/package/components/resources/resourceTypesFilter.js +21 -0
  111. package/package/components/restartFromStepPath.d.ts +39 -0
  112. package/package/components/restartFromStepPath.js +89 -0
  113. package/package/components/runs/JobDetailFieldConfig.d.ts +1 -0
  114. package/package/components/runs/JobDetailFieldConfig.js +57 -10
  115. package/package/components/runs/JobDetailHeader.svelte +24 -3
  116. package/package/components/runs/runsFilter.d.ts +1 -1
  117. package/package/components/schema/FlowPropertyEditor.svelte +30 -1
  118. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +5 -2
  119. package/package/components/search/GlobalSearchModal.svelte +8 -1
  120. package/package/components/select/Select.svelte +1 -1
  121. package/package/components/settings/CreateToken.svelte +48 -77
  122. package/package/components/settings/EditTokenScopesModal.svelte +57 -0
  123. package/package/components/settings/EditTokenScopesModal.svelte.d.ts +10 -0
  124. package/package/components/settings/ScopesPicker.svelte +43 -0
  125. package/package/components/settings/ScopesPicker.svelte.d.ts +11 -0
  126. package/package/components/settings/TokensTable.svelte +51 -15
  127. package/package/components/sidebar/OperatorMenu.svelte +6 -0
  128. package/package/components/sidebar/SidebarContent.svelte +11 -1
  129. package/package/components/triggers/AddTriggersButton.svelte +6 -0
  130. package/package/components/triggers/CaptureWrapper.svelte +19 -1
  131. package/package/components/triggers/TriggerEditorToolbar.svelte.d.ts +1 -1
  132. package/package/components/triggers/TriggerModeToggle.svelte +36 -7
  133. package/package/components/triggers/TriggerModeToggle.svelte.d.ts +1 -1
  134. package/package/components/triggers/TriggerSuspendedJobsModal.svelte.d.ts +1 -1
  135. package/package/components/triggers/TriggersEditor.svelte +5 -1
  136. package/package/components/triggers/TriggersWrapper.svelte +10 -0
  137. package/package/components/triggers/azure/AzureCapture.svelte +41 -0
  138. package/package/components/triggers/azure/AzureCapture.svelte.d.ts +44 -0
  139. package/package/components/triggers/azure/AzureTriggerEditor.svelte +20 -0
  140. package/package/components/triggers/azure/AzureTriggerEditor.svelte.d.ts +9 -0
  141. package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte +301 -0
  142. package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte.d.ts +16 -0
  143. package/package/components/triggers/azure/AzureTriggerEditorInner.svelte +422 -0
  144. package/package/components/triggers/azure/AzureTriggerEditorInner.svelte.d.ts +25 -0
  145. package/package/components/triggers/azure/AzureTriggerPanel.svelte +55 -0
  146. package/package/components/triggers/azure/AzureTriggerPanel.svelte.d.ts +10 -0
  147. package/{dist/sharedUtils/components/triggers/kafka → package/components/triggers/azure}/utils.d.ts +1 -1
  148. package/package/components/triggers/azure/utils.js +56 -0
  149. package/package/components/triggers/email/EmailTriggerEditorInner.svelte +2 -0
  150. package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +9 -3
  151. package/package/components/triggers/http/RouteEditorInner.svelte +2 -0
  152. package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +9 -3
  153. package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +9 -3
  154. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +9 -3
  155. package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +9 -3
  156. package/package/components/triggers/schedules/ScheduleEditorInner.svelte +9 -3
  157. package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +9 -3
  158. package/package/components/triggers/triggers.svelte.d.ts +1 -0
  159. package/package/components/triggers/triggers.svelte.js +23 -1
  160. package/package/components/triggers/utils.js +20 -0
  161. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +9 -3
  162. package/package/components/triggers.d.ts +1 -1
  163. package/package/components/useNestedRestartState.svelte.d.ts +56 -0
  164. package/package/components/useNestedRestartState.svelte.js +320 -0
  165. package/package/components/workspaceSettings/SharedUiSettings.svelte +175 -0
  166. package/package/components/workspaceSettings/SharedUiSettings.svelte.d.ts +3 -0
  167. package/package/gen/core/OpenAPI.js +1 -1
  168. package/package/gen/schemas.gen.d.ts +294 -24
  169. package/package/gen/schemas.gen.js +297 -25
  170. package/package/gen/services.gen.d.ts +247 -4
  171. package/package/gen/services.gen.js +498 -7
  172. package/package/gen/types.gen.d.ts +990 -37
  173. package/package/hubPaths.json +2 -5
  174. package/package/infer.d.ts +1 -1
  175. package/package/infer.js +37 -51
  176. package/package/mcpEndpointTools.js +60 -4
  177. package/package/script_helpers.js +17 -0
  178. package/package/stores.d.ts +7 -0
  179. package/package/stores.js +6 -1
  180. package/package/system_prompts/index.d.ts +1 -0
  181. package/package/system_prompts/index.js +8 -0
  182. package/package/system_prompts/prompts.d.ts +16 -13
  183. package/package/system_prompts/prompts.js +653 -43
  184. package/package/templates/ci_test_bun.ts.template +8 -0
  185. package/package/templates/ci_test_python.py.template +8 -0
  186. package/package/utils/forkConflict.d.ts +26 -0
  187. package/package/utils/forkConflict.js +56 -0
  188. package/package/utils_deployable.d.ts +164 -121
  189. package/package/utils_deployable.js +61 -11
  190. package/package/utils_workspace_deploy.js +3 -1
  191. package/package.json +29 -5
  192. package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +0 -2
  193. package/dist/sharedUtils/base.d.ts +0 -1
  194. package/dist/sharedUtils/cloud.d.ts +0 -1
  195. package/dist/sharedUtils/common.d.ts +0 -111
  196. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +0 -5
  197. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +0 -5
  198. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +0 -5
  199. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +0 -13
  200. package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +0 -11
  201. package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +0 -95
  202. package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +0 -6
  203. package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +0 -7
  204. package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +0 -33
  205. package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +0 -10
  206. package/dist/sharedUtils/components/apps/editor/component/components.d.ts +0 -5371
  207. package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +0 -3
  208. package/dist/sharedUtils/components/apps/editor/component/index.d.ts +0 -3
  209. package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +0 -7
  210. package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +0 -3
  211. package/dist/sharedUtils/components/apps/gridUtils.d.ts +0 -14
  212. package/dist/sharedUtils/components/apps/inputType.d.ts +0 -178
  213. package/dist/sharedUtils/components/apps/rx.d.ts +0 -29
  214. package/dist/sharedUtils/components/apps/sharedTypes.d.ts +0 -21
  215. package/dist/sharedUtils/components/apps/types.d.ts +0 -274
  216. package/dist/sharedUtils/components/assets/lib.d.ts +0 -25
  217. package/dist/sharedUtils/components/common/alert/model.d.ts +0 -2
  218. package/dist/sharedUtils/components/common/badge/model.d.ts +0 -8
  219. package/dist/sharedUtils/components/common/button/model.d.ts +0 -45
  220. package/dist/sharedUtils/components/common/fileInput/model.d.ts +0 -1
  221. package/dist/sharedUtils/components/common/index.d.ts +0 -24
  222. package/dist/sharedUtils/components/common/skeleton/model.d.ts +0 -21
  223. package/dist/sharedUtils/components/dbTypes.d.ts +0 -14
  224. package/dist/sharedUtils/components/diff_drawer.d.ts +0 -26
  225. package/dist/sharedUtils/components/ducklake.d.ts +0 -1
  226. package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +0 -7
  227. package/dist/sharedUtils/components/icons/index.d.ts +0 -101
  228. package/dist/sharedUtils/components/random_positive_adjetive.d.ts +0 -1
  229. package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +0 -10
  230. package/dist/sharedUtils/components/raw_apps/utils.d.ts +0 -15
  231. package/dist/sharedUtils/components/triggers/email/utils.d.ts +0 -4
  232. package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +0 -2
  233. package/dist/sharedUtils/components/triggers/http/utils.d.ts +0 -11
  234. package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +0 -2
  235. package/dist/sharedUtils/components/triggers/nats/utils.d.ts +0 -2
  236. package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +0 -8
  237. package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +0 -2
  238. package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +0 -32
  239. package/dist/sharedUtils/components/triggers/utils.d.ts +0 -80
  240. package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +0 -2
  241. package/dist/sharedUtils/components/triggers.d.ts +0 -20
  242. package/dist/sharedUtils/gen/core/ApiError.d.ts +0 -10
  243. package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +0 -13
  244. package/dist/sharedUtils/gen/core/ApiResult.d.ts +0 -7
  245. package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +0 -26
  246. package/dist/sharedUtils/gen/core/OpenAPI.d.ts +0 -27
  247. package/dist/sharedUtils/gen/core/request.d.ts +0 -29
  248. package/dist/sharedUtils/gen/index.d.ts +0 -6
  249. package/dist/sharedUtils/gen/schemas.gen.d.ts +0 -7036
  250. package/dist/sharedUtils/gen/services.gen.d.ts +0 -6047
  251. package/dist/sharedUtils/gen/types.gen.d.ts +0 -21881
  252. package/dist/sharedUtils/history.svelte.d.ts +0 -9
  253. package/dist/sharedUtils/hub.d.ts +0 -49
  254. package/dist/sharedUtils/jsr.json +0 -6
  255. package/dist/sharedUtils/lib.d.ts +0 -5
  256. package/dist/sharedUtils/lib.es.js +0 -1588
  257. package/dist/sharedUtils/package.json +0 -12
  258. package/dist/sharedUtils/schema.d.ts +0 -3
  259. package/dist/sharedUtils/stores.d.ts +0 -97
  260. package/dist/sharedUtils/svelte5Utils.svelte.d.ts +0 -80
  261. package/dist/sharedUtils/toast.d.ts +0 -8
  262. package/dist/sharedUtils/utils.d.ts +0 -265
  263. package/package/components/copilot/chat/flow/openFlowZod.js +0 -24
  264. /package/package/components/copilot/chat/flow/{openFlowZod.d.ts → openFlowZod.gen.d.ts} +0 -0
@@ -3,15 +3,24 @@ import { untrack } from 'svelte';
3
3
  import { Alert, Button } from './common';
4
4
  import S3FilePickerInner from './S3FilePickerInner.svelte';
5
5
  import { workspaceStore } from '../stores';
6
- import { Loader, Loader2 } from 'lucide-svelte';
6
+ import { base } from '../base';
7
+ import { Loader, Loader2, ChevronDown, ChevronRight, ExternalLink } from 'lucide-svelte';
7
8
  import { hubPaths } from '../hub';
8
- import { tryEvery } from '../utils';
9
+ import { sleep } from '../utils';
10
+ const CLONE_MARKER_FILE = '.windmill_clone_complete';
11
+ const POLL_INTERVAL_MS = 1500;
12
+ const MAX_POLL_DURATION_MS = 30 * 60 * 1000; // 30 minutes
9
13
  let s3FilePicker = $state();
10
14
  let isLoadingCommitHash = $state(false);
11
15
  let isLoadingRepoClone = $state(false);
12
16
  let isCheckingPathExists = $state(false);
13
17
  let pathExists = $state(null);
14
18
  let error = $state(null);
19
+ // Live job state for the running clone
20
+ let runningJobId = $state(null);
21
+ let runningLogs = $state('');
22
+ let logsExpanded = $state(false);
23
+ let cancelRequested = $state(false);
15
24
  let { gitRepoResourcePath, gitSshIdentity, commitHashInput = $bindable() } = $props();
16
25
  let commitHash = $derived(commitHashInput);
17
26
  async function populateS3WithGitRepo() {
@@ -19,110 +28,251 @@ async function populateS3WithGitRepo() {
19
28
  if (!workspace)
20
29
  return;
21
30
  const payload = {
22
- workspace: workspace,
31
+ workspace,
23
32
  resource_path: gitRepoResourcePath,
24
33
  git_ssh_identity: gitSshIdentity,
25
- commit: commitHash,
34
+ commit: commitHash
26
35
  };
27
36
  isLoadingRepoClone = true;
28
- const jobId = await JobService.runScriptByPath({
29
- workspace,
30
- path: hubPaths.cloneRepoToS3forGitRepoViewer,
31
- requestBody: payload,
32
- skipPreprocessor: true
33
- });
34
- let jobSuccess = false;
35
- await tryEvery({
36
- tryCode: async () => {
37
- const testResult = await JobService.getCompletedJob({ workspace, id: jobId });
38
- jobSuccess = !!testResult.success;
39
- if (jobSuccess) {
40
- await JobService.getCompletedJobResult({ workspace, id: jobId });
41
- }
42
- else {
43
- error = testResult.result.error.message ?? "Failed to clone";
37
+ error = null;
38
+ runningLogs = '';
39
+ cancelRequested = false;
40
+ logsExpanded = true;
41
+ let jobId;
42
+ try {
43
+ jobId = await JobService.runScriptByPath({
44
+ workspace,
45
+ path: hubPaths.cloneRepoToS3forGitRepoViewer,
46
+ requestBody: payload,
47
+ skipPreprocessor: true
48
+ });
49
+ }
50
+ catch (err) {
51
+ error = `Failed to start clone job: ${err?.message ?? err}`;
52
+ isLoadingRepoClone = false;
53
+ return;
54
+ }
55
+ runningJobId = jobId;
56
+ const startedAt = Date.now();
57
+ let logOffset = 0;
58
+ let isCompleted = false;
59
+ while (!isCompleted) {
60
+ if (cancelRequested) {
61
+ try {
62
+ await JobService.cancelQueuedJob({
63
+ workspace,
64
+ id: jobId,
65
+ requestBody: { reason: 'cancelled by user from git repo viewer' }
66
+ });
44
67
  }
45
- },
46
- timeoutCode: async () => {
68
+ catch (_err) { }
69
+ error = 'Repository clone cancelled.';
70
+ break;
71
+ }
72
+ if (Date.now() - startedAt > MAX_POLL_DURATION_MS) {
47
73
  try {
48
74
  await JobService.cancelQueuedJob({
49
75
  workspace,
50
76
  id: jobId,
51
- requestBody: { reason: `job timed out after 60s` }
77
+ requestBody: { reason: 'git repo clone exceeded 30 min' }
52
78
  });
53
79
  }
54
- catch (err) { }
55
- },
56
- interval: 1000,
57
- timeout: 60000
58
- });
59
- isLoadingRepoClone = false;
60
- if (jobSuccess) {
61
- pathExists = true;
80
+ catch (_err) { }
81
+ error = `Repository clone exceeded ${Math.round(MAX_POLL_DURATION_MS / 60000)} min and was cancelled.`;
82
+ break;
83
+ }
84
+ try {
85
+ const update = await JobService.getJobUpdates({
86
+ workspace,
87
+ id: jobId,
88
+ running: true,
89
+ logOffset
90
+ });
91
+ if (update.new_logs) {
92
+ runningLogs += update.new_logs;
93
+ }
94
+ if (typeof update.log_offset === 'number') {
95
+ logOffset = update.log_offset;
96
+ }
97
+ if (update.completed) {
98
+ isCompleted = true;
99
+ break;
100
+ }
101
+ }
102
+ catch (_err) {
103
+ // Transient API failure — keep polling.
104
+ }
105
+ await sleep(POLL_INTERVAL_MS);
106
+ }
107
+ if (isCompleted) {
108
+ try {
109
+ const completed = await JobService.getCompletedJob({ workspace, id: jobId });
110
+ if (completed.success) {
111
+ // Verify the marker so partial uploads aren't shown as complete.
112
+ const s3Path = `gitrepos/${workspace}/${gitRepoResourcePath}/${commitHash}/`;
113
+ try {
114
+ const check = await HelpersService.checkS3FolderExists({
115
+ workspace,
116
+ fileKey: s3Path,
117
+ markerFile: CLONE_MARKER_FILE
118
+ });
119
+ if (check.exists) {
120
+ pathExists = true;
121
+ logsExpanded = false;
122
+ }
123
+ else {
124
+ pathExists = false;
125
+ error =
126
+ 'Clone job finished but the completion marker is missing. The repository may have been synced with an older clone script — re-run to refresh.';
127
+ }
128
+ }
129
+ catch (err) {
130
+ error = `Failed to verify clone completion: ${err?.message ?? err}`;
131
+ }
132
+ }
133
+ else {
134
+ const errMsg = completed.result?.error?.message ??
135
+ completed.result?.error ??
136
+ 'Clone job failed without an error message.';
137
+ error = typeof errMsg === 'string' ? errMsg : JSON.stringify(errMsg);
138
+ }
139
+ }
140
+ catch (err) {
141
+ error = `Failed to read clone job result: ${err?.message ?? err}`;
142
+ }
62
143
  }
144
+ isLoadingRepoClone = false;
63
145
  }
64
- async function fetchGitRepoData() {
146
+ function cancelClone() {
147
+ cancelRequested = true;
148
+ }
149
+ async function fetchCommitHash() {
150
+ if (commitHash)
151
+ return;
65
152
  try {
66
153
  error = null;
67
- // Step 1: Fetch commit hash if not provided
68
- if (!commitHash) {
69
- isLoadingCommitHash = true;
70
- error = null;
71
- const result = await ResourceService.getGitCommitHash({
72
- workspace: $workspaceStore,
73
- path: gitRepoResourcePath,
74
- gitSshIdentity: gitSshIdentity?.join(",")
75
- });
76
- commitHashInput = result.commit_hash;
77
- isLoadingCommitHash = false;
78
- }
79
- // Step 2: Check if S3 path exists
80
- if (commitHash) {
81
- isCheckingPathExists = true;
82
- const s3Path = `gitrepos/${$workspaceStore}/${gitRepoResourcePath}/${commitHash}/`;
83
- const pathCheck = await HelpersService.checkS3FolderExists({
84
- workspace: $workspaceStore,
85
- fileKey: s3Path
86
- });
87
- pathExists = pathCheck.exists && pathCheck.is_folder;
88
- isCheckingPathExists = false;
89
- }
154
+ isLoadingCommitHash = true;
155
+ const result = await ResourceService.getGitCommitHash({
156
+ workspace: $workspaceStore,
157
+ path: gitRepoResourcePath,
158
+ gitSshIdentity: gitSshIdentity?.join(',')
159
+ });
160
+ commitHashInput = result.commit_hash;
90
161
  }
91
162
  catch (err) {
92
163
  error = `Failed to load git repository ${gitRepoResourcePath}: ${err.status} - ${err.message || 'Unknown error'}: ${err.body}`;
164
+ }
165
+ finally {
93
166
  isLoadingCommitHash = false;
167
+ }
168
+ }
169
+ async function checkS3Path() {
170
+ if (!commitHash)
171
+ return;
172
+ try {
173
+ error = null;
174
+ isCheckingPathExists = true;
175
+ const s3Path = `gitrepos/${$workspaceStore}/${gitRepoResourcePath}/${commitHash}/`;
176
+ const pathCheck = await HelpersService.checkS3FolderExists({
177
+ workspace: $workspaceStore,
178
+ fileKey: s3Path,
179
+ markerFile: CLONE_MARKER_FILE
180
+ });
181
+ pathExists = pathCheck.exists && pathCheck.is_folder;
182
+ }
183
+ catch (err) {
184
+ error = `Failed to load git repository ${gitRepoResourcePath}: ${err.status} - ${err.message || 'Unknown error'}: ${err.body}`;
185
+ }
186
+ finally {
94
187
  isCheckingPathExists = false;
95
188
  }
96
189
  }
190
+ $effect(() => {
191
+ gitRepoResourcePath;
192
+ untrack(() => fetchCommitHash());
193
+ });
97
194
  $effect(() => {
98
195
  ;
99
- [commitHashInput, gitRepoResourcePath];
100
- untrack(() => {
101
- fetchGitRepoData();
102
- });
196
+ [commitHash, gitRepoResourcePath];
197
+ untrack(() => checkS3Path());
103
198
  });
104
199
  $effect(() => {
105
200
  ;
106
- [commitHash, pathExists, isCheckingPathExists, isLoadingCommitHash];
107
- untrack(() => {
108
- s3FilePicker?.open(undefined);
109
- });
201
+ [s3FilePicker, commitHash, gitRepoResourcePath, pathExists];
202
+ untrack(() => s3FilePicker?.reloadContent());
110
203
  });
111
204
  </script>
112
205
 
113
- {#if error}
114
- <Alert type="error" title="Error Loading Repository">
115
- <p>{error}</p>
116
- </Alert>
206
+ {#if error && !isLoadingRepoClone}
207
+ <div class="p-4 space-y-3">
208
+ <Alert type="error" title="Error Loading Repository">
209
+ <p class="whitespace-pre-wrap break-words">{error}</p>
210
+ {#if runningJobId}
211
+ <a
212
+ class="inline-flex items-center gap-1 mt-2 text-sm underline"
213
+ href={`${base}/run/${runningJobId}?workspace=${$workspaceStore}`}
214
+ target="_blank"
215
+ rel="noreferrer noopener"
216
+ >
217
+ View job logs <ExternalLink size={12} />
218
+ </a>
219
+ {/if}
220
+ </Alert>
221
+ {#if runningLogs}
222
+ <details class="text-xs">
223
+ <summary class="cursor-pointer text-secondary">Last clone logs</summary>
224
+ <pre
225
+ class="mt-2 p-2 bg-surface-secondary rounded max-h-64 overflow-auto whitespace-pre-wrap"
226
+ >{runningLogs}</pre
227
+ >
228
+ </details>
229
+ {/if}
230
+ <Button onclick={populateS3WithGitRepo} color="blue">Retry</Button>
231
+ </div>
117
232
  {:else if isLoadingCommitHash}
118
233
  <div class="flex items-center gap-2 p-4">
119
234
  <Loader2 class="h-4 w-4 animate-spin" />
120
235
  <span class="text-secondary">Fetching latest commit hash...</span>
121
236
  </div>
122
237
  {:else if isLoadingRepoClone}
123
- <div class="flex items-center gap-2 p-4">
124
- <Loader class="h-4 w-4 animate-spin" />
125
- <span class="text-secondary">Cloning repository...</span>
238
+ <div class="p-4 space-y-3">
239
+ <div class="flex items-center justify-between gap-2">
240
+ <div class="flex items-center gap-2">
241
+ <Loader class="h-4 w-4 animate-spin" />
242
+ <span class="text-secondary">Cloning repository...</span>
243
+ </div>
244
+ <div class="flex items-center gap-2">
245
+ {#if runningJobId}
246
+ <a
247
+ class="inline-flex items-center gap-1 text-xs underline text-secondary"
248
+ href={`${base}/run/${runningJobId}?workspace=${$workspaceStore}`}
249
+ target="_blank"
250
+ rel="noreferrer noopener"
251
+ >
252
+ Job <ExternalLink size={12} />
253
+ </a>
254
+ {/if}
255
+ <Button size="xs" color="light" variant="border" onclick={cancelClone}>Cancel</Button>
256
+ </div>
257
+ </div>
258
+ <button
259
+ type="button"
260
+ class="flex items-center gap-1 text-xs text-secondary hover:text-primary"
261
+ onclick={() => (logsExpanded = !logsExpanded)}
262
+ >
263
+ {#if logsExpanded}
264
+ <ChevronDown size={12} />
265
+ {:else}
266
+ <ChevronRight size={12} />
267
+ {/if}
268
+ Logs
269
+ </button>
270
+ {#if logsExpanded}
271
+ <pre
272
+ class="mt-1 p-2 bg-surface-secondary rounded text-xs max-h-64 overflow-auto whitespace-pre-wrap"
273
+ >{runningLogs || '(waiting for output...)'}</pre
274
+ >
275
+ {/if}
126
276
  </div>
127
277
  {:else if commitHash && isCheckingPathExists}
128
278
  <div class="flex items-center gap-2 p-4">
@@ -137,31 +287,35 @@ $effect(() => {
137
287
  <Button onclick={populateS3WithGitRepo} color="blue">Load Repository Contents</Button>
138
288
  </div>
139
289
  {:else if commitHash && pathExists === true}
140
- <S3FilePickerInner
141
- bind:this={s3FilePicker}
142
- readOnlyMode
143
- hideS3SpecificDetails
144
- rootPath={`gitrepos/${$workspaceStore}/${gitRepoResourcePath}/${commitHash}/`}
145
- listStoredFilesRequest={HelpersService.listGitRepoFiles}
146
- loadFilePreviewRequest={HelpersService.loadGitRepoFilePreview}
147
- testConnectionRequest={(async (_d) => {
148
- const bucketConfig: any = await SettingService.getGlobal({ key: 'object_store_cache_config' })
149
- return SettingService.testObjectStorageConfig({
150
- requestBody: bucketConfig
151
- })
152
- }) as any}
153
- loadFileMetadataRequest={HelpersService.loadGitRepoFileMetadata}
154
- >
155
- {#snippet replaceUnauthorizedWarning()}
156
- <div class="mb-2">
157
- <Alert type="error" title="Cannot view git repo">
158
- <p>
159
- The git repo resource you are trying to access either doesn't exist or you don't have
160
- access to it. Make sure the resource path is correct and that you have visibility over
161
- the resource.
162
- </p>
163
- </Alert>
164
- </div>
165
- {/snippet}
166
- </S3FilePickerInner>
290
+ {#key `${gitRepoResourcePath}-${commitHash}`}
291
+ <S3FilePickerInner
292
+ bind:this={s3FilePicker}
293
+ readOnlyMode
294
+ hideS3SpecificDetails
295
+ rootPath={`gitrepos/${$workspaceStore}/${gitRepoResourcePath}/${commitHash}/`}
296
+ listStoredFilesRequest={HelpersService.listGitRepoFiles}
297
+ loadFilePreviewRequest={HelpersService.loadGitRepoFilePreview}
298
+ testConnectionRequest={(async (_d) => {
299
+ const bucketConfig: any = await SettingService.getGlobal({
300
+ key: 'object_store_cache_config'
301
+ })
302
+ return SettingService.testObjectStorageConfig({
303
+ requestBody: bucketConfig
304
+ })
305
+ }) as any}
306
+ loadFileMetadataRequest={HelpersService.loadGitRepoFileMetadata}
307
+ >
308
+ {#snippet replaceUnauthorizedWarning()}
309
+ <div class="mb-2">
310
+ <Alert type="error" title="Cannot view git repo">
311
+ <p>
312
+ The git repo resource you are trying to access either doesn't exist or you don't have
313
+ access to it. Make sure the resource path is correct and that you have visibility over
314
+ the resource.
315
+ </p>
316
+ </Alert>
317
+ </div>
318
+ {/snippet}
319
+ </S3FilePickerInner>
320
+ {/key}
167
321
  {/if}
@@ -38,7 +38,7 @@ let s3StorageConfigured = $state(true);
38
38
  async function checkS3Storage() {
39
39
  try {
40
40
  if ($workspaceStore) {
41
- const settings = await WorkspaceService.getSettings({ workspace: $workspaceStore });
41
+ const settings = await WorkspaceService.getPublicSettings({ workspace: $workspaceStore });
42
42
  s3StorageConfigured = settings.large_file_storage?.s3_resource_path !== undefined;
43
43
  }
44
44
  }
@@ -156,6 +156,33 @@ export async function saveSettings() {
156
156
  }
157
157
  // Build the full global_settings object for the bulk PUT
158
158
  const globalSettings = { ...$values };
159
+ // Send explicit null for keys that were set on load but are now
160
+ // missing/cleared, so the Merge-mode bulk endpoint deletes them
161
+ // instead of silently preserving the old DB value. Covers both:
162
+ // - YAML mode: user removed a line / set it to null / set it to {}.
163
+ // - Form mode: user toggled a setting off (e.g.
164
+ // object_store_cache_config), making the value undefined.
165
+ const isClearedValue = (v) => {
166
+ if (v === undefined || v === null)
167
+ return true;
168
+ if (typeof v === 'object') {
169
+ return Array.isArray(v) ? v.length === 0 : Object.keys(v).length === 0;
170
+ }
171
+ return false;
172
+ };
173
+ for (const key of Object.keys(initialValues ?? {})) {
174
+ if (excludedKeys.has(key))
175
+ continue;
176
+ if (key === 'oauths' || key === 'require_preexisting_user_for_oauth')
177
+ continue;
178
+ if (!isClearedValue(globalSettings[key]))
179
+ continue;
180
+ // Only flag for deletion if it was non-empty before — otherwise
181
+ // every save would delete-then-recreate harmless `{}`/`[]` defaults.
182
+ if (isClearedValue(initialValues[key]))
183
+ continue;
184
+ globalSettings[key] = null;
185
+ }
159
186
  // Include oauths and require_preexisting_user_for_oauth
160
187
  if (!deepEqual(initialOauths, oauths)) {
161
188
  globalSettings['oauths'] = oauths;
@@ -273,7 +300,7 @@ function stripEmpty(obj) {
273
300
  }
274
301
  function getSettingsForCategory(category) {
275
302
  if (category === 'Auth/OAuth/SAML') {
276
- return scimSamlSetting;
303
+ return [...(settings[category] ?? []), ...scimSamlSetting];
277
304
  }
278
305
  const base = settings[category] ?? [];
279
306
  // In quick setup, reorder Core: base settings (without license_key), then extras from Jobs
@@ -383,27 +410,20 @@ export function isDirty(category) {
383
410
  return dirtyCategories[category] ?? false;
384
411
  }
385
412
  export function discardCategory(category) {
413
+ const categorySettings = getSettingsForCategory(category);
414
+ for (const s of categorySettings) {
415
+ const v = initialValues[s.key];
416
+ $values[s.key] = v !== undefined ? JSON.parse(JSON.stringify(v)) : undefined;
417
+ }
386
418
  if (category === 'Auth/OAuth/SAML') {
387
- for (const s of scimSamlSetting) {
388
- const v = initialValues[s.key];
389
- $values[s.key] = v !== undefined ? JSON.parse(JSON.stringify(v)) : undefined;
390
- }
391
419
  oauths = JSON.parse(JSON.stringify(initialOauths));
392
420
  requirePreexistingUserForOauth = initialRequirePreexistingUserForOauth;
393
421
  const account_identifier = initialOauths?.snowflake_oauth?.connect_config?.extra_params?.account_identifier;
394
422
  snowflakeAccountIdentifier = account_identifier ?? '';
395
423
  }
396
- else {
397
- const categorySettings = getSettingsForCategory(category);
398
- for (const s of categorySettings) {
399
- const v = initialValues[s.key];
400
- $values[s.key] = v !== undefined ? JSON.parse(JSON.stringify(v)) : undefined;
401
- }
402
- if (category === 'Registries') {
403
- const v = initialValues['workspace_registries'];
404
- $values['workspace_registries'] =
405
- v !== undefined ? JSON.parse(JSON.stringify(v)) : undefined;
406
- }
424
+ else if (category === 'Registries') {
425
+ const v = initialValues['workspace_registries'];
426
+ $values['workspace_registries'] = v !== undefined ? JSON.parse(JSON.stringify(v)) : undefined;
407
427
  }
408
428
  }
409
429
  export function discardAll() {