windmill-components 1.687.0 → 1.695.0

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 +28 -4
  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
@@ -0,0 +1,412 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { z } from 'zod';
3
+ vi.mock('monaco-editor', () => ({
4
+ editor: {}
5
+ }));
6
+ vi.mock('$lib/stores', () => ({
7
+ workspaceStore: { subscribe: () => () => undefined }
8
+ }));
9
+ vi.mock('$lib/components/flows/flowTree', () => ({
10
+ findModuleInModules: () => undefined
11
+ }));
12
+ vi.mock('$lib/gen', () => ({
13
+ ScriptService: {},
14
+ FlowService: {},
15
+ JobService: {},
16
+ ScheduleService: {
17
+ previewSchedule: vi.fn(),
18
+ createSchedule: vi.fn()
19
+ },
20
+ HttpTriggerService: { createHttpTrigger: vi.fn() },
21
+ WebsocketTriggerService: { createWebsocketTrigger: vi.fn() },
22
+ KafkaTriggerService: { createKafkaTrigger: vi.fn() },
23
+ NatsTriggerService: { createNatsTrigger: vi.fn() },
24
+ PostgresTriggerService: { createPostgresTrigger: vi.fn() },
25
+ MqttTriggerService: { createMqttTrigger: vi.fn() },
26
+ SqsTriggerService: { createSqsTrigger: vi.fn() },
27
+ GcpTriggerService: { createGcpTrigger: vi.fn() },
28
+ AzureTriggerService: { createAzureTrigger: vi.fn() }
29
+ }));
30
+ vi.mock('$lib/utils', () => ({
31
+ emptyString: (value) => !value
32
+ }));
33
+ vi.mock('$lib/scripts', () => ({
34
+ scriptLangToEditorLang: (language) => language
35
+ }));
36
+ vi.mock('$lib/aiStore', () => ({
37
+ getCurrentModel: () => undefined
38
+ }));
39
+ vi.mock('@leeoniya/ufuzzy', () => ({
40
+ default: class {
41
+ search() {
42
+ return [[], [], []];
43
+ }
44
+ }
45
+ }));
46
+ describe('createToolDef', () => {
47
+ it('builds the create_trigger schema without top-level composition', async () => {
48
+ const { createToolDef } = await import('./shared');
49
+ const { createTriggerToolSchema } = await import('./workspaceToolsZod.gen');
50
+ const toolDef = createToolDef(createTriggerToolSchema, 'create_trigger', 'Create a trigger');
51
+ const parameters = toolDef.function.parameters;
52
+ expect(parameters).toBeDefined();
53
+ expect(parameters?.type).toBe('object');
54
+ expect(parameters?.anyOf).toBeUndefined();
55
+ expect(parameters?.oneOf).toBeUndefined();
56
+ expect(parameters?.allOf).toBeUndefined();
57
+ expect(parameters?.properties?.kind?.enum).toContain('http');
58
+ expect(parameters?.properties?.config?.anyOf?.length).toBeGreaterThan(1);
59
+ });
60
+ it('does not expose runnable target fields on workspace mutation tools', async () => {
61
+ const { createWorkspaceMutationTools } = await import('./workspaceTools');
62
+ const [scheduleTool, triggerTool] = createWorkspaceMutationTools();
63
+ const scheduleParameters = scheduleTool.def.function.parameters;
64
+ expect(scheduleParameters?.properties?.script_path).toBeUndefined();
65
+ expect(scheduleParameters?.properties?.is_flow).toBeUndefined();
66
+ const triggerParameters = triggerTool.def.function.parameters;
67
+ const triggerConfigVariants = triggerParameters?.properties?.config?.anyOf ?? [];
68
+ expect(triggerConfigVariants.length).toBeGreaterThan(1);
69
+ for (const variant of triggerConfigVariants) {
70
+ expect(variant?.properties?.script_path).toBeUndefined();
71
+ expect(variant?.properties?.is_flow).toBeUndefined();
72
+ }
73
+ });
74
+ });
75
+ describe('processToolCall', () => {
76
+ it('returns pre-confirmation validation errors without asking for confirmation', async () => {
77
+ const { createToolDef, processToolCall } = await import('./shared');
78
+ const error = 'the script needs to be deployed before doing this action';
79
+ const fn = vi.fn();
80
+ const requestConfirmation = vi.fn();
81
+ const setToolStatus = vi.fn();
82
+ const result = await processToolCall({
83
+ tools: [
84
+ {
85
+ def: createToolDef(z.object({}), 'create_schedule', 'Create schedule'),
86
+ requiresConfirmation: true,
87
+ showDetails: true,
88
+ validateBeforeConfirmation: () => error,
89
+ fn
90
+ }
91
+ ],
92
+ toolCall: {
93
+ id: 'call_1',
94
+ type: 'function',
95
+ function: { name: 'create_schedule', arguments: '{}' }
96
+ },
97
+ helpers: {},
98
+ workspace: 'test-workspace',
99
+ toolCallbacks: {
100
+ setToolStatus,
101
+ removeToolStatus: vi.fn(),
102
+ requestConfirmation
103
+ }
104
+ });
105
+ expect(requestConfirmation).not.toHaveBeenCalled();
106
+ expect(fn).not.toHaveBeenCalled();
107
+ expect(setToolStatus).toHaveBeenCalledWith('call_1', expect.objectContaining({
108
+ content: error,
109
+ error,
110
+ isLoading: false,
111
+ needsConfirmation: false,
112
+ showDetails: true
113
+ }));
114
+ expect(result.content).toBe(error);
115
+ });
116
+ it('continues to confirmation when pre-confirmation validation passes', async () => {
117
+ const { createToolDef, processToolCall } = await import('./shared');
118
+ const fn = vi.fn().mockResolvedValue('ok');
119
+ const requestConfirmation = vi.fn().mockResolvedValue(true);
120
+ const setToolStatus = vi.fn();
121
+ const result = await processToolCall({
122
+ tools: [
123
+ {
124
+ def: createToolDef(z.object({}), 'create_schedule', 'Create schedule'),
125
+ requiresConfirmation: true,
126
+ confirmationMessage: 'Create schedule',
127
+ validateBeforeConfirmation: () => undefined,
128
+ fn
129
+ }
130
+ ],
131
+ toolCall: {
132
+ id: 'call_2',
133
+ type: 'function',
134
+ function: { name: 'create_schedule', arguments: '{}' }
135
+ },
136
+ helpers: {},
137
+ workspace: 'test-workspace',
138
+ toolCallbacks: {
139
+ setToolStatus,
140
+ removeToolStatus: vi.fn(),
141
+ requestConfirmation
142
+ }
143
+ });
144
+ expect(requestConfirmation).toHaveBeenCalledWith('call_2');
145
+ expect(fn).toHaveBeenCalled();
146
+ expect(result.content).toBe('ok');
147
+ });
148
+ it('blocks workspace mutation tools for undeployed scripts and flows', async () => {
149
+ const { processToolCall } = await import('./shared');
150
+ const { createWorkspaceMutationTools } = await import('./workspaceTools');
151
+ const setToolStatus = vi.fn();
152
+ const requestConfirmation = vi.fn();
153
+ const workspaceMutationTools = createWorkspaceMutationTools();
154
+ const scriptResult = await processToolCall({
155
+ tools: workspaceMutationTools,
156
+ toolCall: {
157
+ id: 'call_3',
158
+ type: 'function',
159
+ function: { name: 'create_schedule', arguments: '{}' }
160
+ },
161
+ helpers: {
162
+ getWorkspaceMutationTarget: () => ({ kind: 'script', path: '', deployed: false })
163
+ },
164
+ workspace: 'test-workspace',
165
+ toolCallbacks: {
166
+ setToolStatus,
167
+ removeToolStatus: vi.fn(),
168
+ requestConfirmation
169
+ }
170
+ });
171
+ expect(scriptResult.content).toBe('the script needs to be deployed before doing this action');
172
+ const flowResult = await processToolCall({
173
+ tools: workspaceMutationTools,
174
+ toolCall: {
175
+ id: 'call_4',
176
+ type: 'function',
177
+ function: { name: 'create_trigger', arguments: '{}' }
178
+ },
179
+ helpers: {
180
+ getWorkspaceMutationTarget: () => ({ kind: 'flow', path: 'f/flow', deployed: false })
181
+ },
182
+ workspace: 'test-workspace',
183
+ toolCallbacks: {
184
+ setToolStatus,
185
+ removeToolStatus: vi.fn(),
186
+ requestConfirmation
187
+ }
188
+ });
189
+ expect(flowResult.content).toBe('the flow needs to be deployed before doing this action');
190
+ expect(requestConfirmation).not.toHaveBeenCalled();
191
+ });
192
+ it('injects runnable target fields into schedule and trigger requests', async () => {
193
+ const gen = (await import('../../../gen'));
194
+ const { processToolCall } = await import('./shared');
195
+ const { createWorkspaceMutationTools } = await import('./workspaceTools');
196
+ const workspaceMutationTools = createWorkspaceMutationTools();
197
+ gen.ScheduleService.previewSchedule.mockReset();
198
+ gen.ScheduleService.createSchedule.mockReset();
199
+ gen.HttpTriggerService.createHttpTrigger.mockReset();
200
+ gen.ScheduleService.previewSchedule.mockResolvedValue({});
201
+ gen.ScheduleService.createSchedule.mockResolvedValue('schedule-created');
202
+ gen.HttpTriggerService.createHttpTrigger.mockResolvedValue('trigger-created');
203
+ const scheduleSetToolStatus = vi.fn();
204
+ const scheduleResult = await processToolCall({
205
+ tools: workspaceMutationTools,
206
+ toolCall: {
207
+ id: 'call_5',
208
+ type: 'function',
209
+ function: {
210
+ name: 'create_schedule',
211
+ arguments: JSON.stringify({
212
+ path: 'f/schedules/current',
213
+ schedule: '0 0 12 * * *',
214
+ timezone: 'UTC',
215
+ args: null
216
+ })
217
+ }
218
+ },
219
+ helpers: {
220
+ getWorkspaceMutationTarget: () => ({
221
+ kind: 'script',
222
+ path: 'f/scripts/current',
223
+ deployed: true
224
+ })
225
+ },
226
+ workspace: 'test-workspace',
227
+ toolCallbacks: {
228
+ setToolStatus: scheduleSetToolStatus,
229
+ removeToolStatus: vi.fn(),
230
+ requestConfirmation: vi.fn().mockResolvedValue(true)
231
+ }
232
+ });
233
+ expect(gen.ScheduleService.createSchedule).toHaveBeenCalledWith({
234
+ workspace: 'test-workspace',
235
+ requestBody: expect.objectContaining({
236
+ script_path: 'f/scripts/current',
237
+ is_flow: false
238
+ })
239
+ });
240
+ expect(scheduleSetToolStatus).toHaveBeenCalledWith('call_5', expect.objectContaining({
241
+ result: expect.objectContaining({
242
+ success: true,
243
+ path: 'f/schedules/current',
244
+ target_path: 'f/scripts/current',
245
+ target_kind: 'script',
246
+ backend_result: 'schedule-created'
247
+ })
248
+ }));
249
+ expect(JSON.parse(scheduleResult.content)).toEqual(expect.objectContaining({
250
+ success: true,
251
+ path: 'f/schedules/current',
252
+ target_path: 'f/scripts/current',
253
+ target_kind: 'script',
254
+ backend_result: 'schedule-created'
255
+ }));
256
+ const triggerSetToolStatus = vi.fn();
257
+ const triggerResult = await processToolCall({
258
+ tools: workspaceMutationTools,
259
+ toolCall: {
260
+ id: 'call_6',
261
+ type: 'function',
262
+ function: {
263
+ name: 'create_trigger',
264
+ arguments: JSON.stringify({
265
+ kind: 'http',
266
+ path: 'f/triggers/current',
267
+ config: {
268
+ route_path: 'api/current',
269
+ http_method: 'post',
270
+ authentication_method: 'none',
271
+ is_static_website: false
272
+ }
273
+ })
274
+ }
275
+ },
276
+ helpers: {
277
+ getWorkspaceMutationTarget: () => ({
278
+ kind: 'flow',
279
+ path: 'f/flows/current',
280
+ deployed: true
281
+ })
282
+ },
283
+ workspace: 'test-workspace',
284
+ toolCallbacks: {
285
+ setToolStatus: triggerSetToolStatus,
286
+ removeToolStatus: vi.fn(),
287
+ requestConfirmation: vi.fn().mockResolvedValue(true)
288
+ }
289
+ });
290
+ expect(gen.HttpTriggerService.createHttpTrigger).toHaveBeenCalledWith({
291
+ workspace: 'test-workspace',
292
+ requestBody: expect.objectContaining({
293
+ script_path: 'f/flows/current',
294
+ is_flow: true
295
+ })
296
+ });
297
+ expect(triggerSetToolStatus).toHaveBeenCalledWith('call_6', expect.objectContaining({
298
+ result: expect.objectContaining({
299
+ success: true,
300
+ kind: 'http',
301
+ path: 'f/triggers/current',
302
+ target_path: 'f/flows/current',
303
+ target_kind: 'flow',
304
+ backend_result: 'trigger-created'
305
+ })
306
+ }));
307
+ expect(JSON.parse(triggerResult.content)).toEqual(expect.objectContaining({
308
+ success: true,
309
+ kind: 'http',
310
+ path: 'f/triggers/current',
311
+ target_path: 'f/flows/current',
312
+ target_kind: 'flow',
313
+ backend_result: 'trigger-created'
314
+ }));
315
+ });
316
+ it('surfaces workspace mutation tool execution errors to the user', async () => {
317
+ const gen = (await import('../../../gen'));
318
+ const { processToolCall } = await import('./shared');
319
+ const { createWorkspaceMutationTools } = await import('./workspaceTools');
320
+ const workspaceMutationTools = createWorkspaceMutationTools();
321
+ gen.ScheduleService.previewSchedule.mockReset();
322
+ gen.ScheduleService.createSchedule.mockReset();
323
+ gen.HttpTriggerService.createHttpTrigger.mockReset();
324
+ gen.ScheduleService.previewSchedule.mockRejectedValue(new Error('backend rejected schedule'));
325
+ const scheduleSetToolStatus = vi.fn();
326
+ const scheduleError = 'Invalid schedule or timezone: backend rejected schedule';
327
+ const scheduleResult = await processToolCall({
328
+ tools: workspaceMutationTools,
329
+ toolCall: {
330
+ id: 'call_7',
331
+ type: 'function',
332
+ function: {
333
+ name: 'create_schedule',
334
+ arguments: JSON.stringify({
335
+ path: 'f/schedules/current',
336
+ schedule: '0 0 12 * * *',
337
+ timezone: 'UTC',
338
+ args: null
339
+ })
340
+ }
341
+ },
342
+ helpers: {
343
+ getWorkspaceMutationTarget: () => ({
344
+ kind: 'script',
345
+ path: 'f/scripts/current',
346
+ deployed: true
347
+ })
348
+ },
349
+ workspace: 'test-workspace',
350
+ toolCallbacks: {
351
+ setToolStatus: scheduleSetToolStatus,
352
+ removeToolStatus: vi.fn(),
353
+ requestConfirmation: vi.fn().mockResolvedValue(true)
354
+ }
355
+ });
356
+ expect(scheduleSetToolStatus).toHaveBeenCalledWith('call_7', expect.objectContaining({
357
+ content: scheduleError,
358
+ error: scheduleError,
359
+ isLoading: false
360
+ }));
361
+ expect(scheduleResult.content).toBe(`Error while calling tool: ${scheduleError}`);
362
+ expect(scheduleSetToolStatus).not.toHaveBeenCalledWith('call_7', expect.objectContaining({
363
+ error: 'An error occurred while calling the tool'
364
+ }));
365
+ gen.ScheduleService.previewSchedule.mockResolvedValue({});
366
+ gen.HttpTriggerService.createHttpTrigger.mockRejectedValue(new Error('backend rejected trigger'));
367
+ const triggerSetToolStatus = vi.fn();
368
+ const triggerError = 'Failed to create HTTP trigger "f/triggers/current": backend rejected trigger';
369
+ const triggerResult = await processToolCall({
370
+ tools: workspaceMutationTools,
371
+ toolCall: {
372
+ id: 'call_8',
373
+ type: 'function',
374
+ function: {
375
+ name: 'create_trigger',
376
+ arguments: JSON.stringify({
377
+ kind: 'http',
378
+ path: 'f/triggers/current',
379
+ config: {
380
+ route_path: 'api/current',
381
+ http_method: 'post',
382
+ authentication_method: 'none',
383
+ is_static_website: false
384
+ }
385
+ })
386
+ }
387
+ },
388
+ helpers: {
389
+ getWorkspaceMutationTarget: () => ({
390
+ kind: 'flow',
391
+ path: 'f/flows/current',
392
+ deployed: true
393
+ })
394
+ },
395
+ workspace: 'test-workspace',
396
+ toolCallbacks: {
397
+ setToolStatus: triggerSetToolStatus,
398
+ removeToolStatus: vi.fn(),
399
+ requestConfirmation: vi.fn().mockResolvedValue(true)
400
+ }
401
+ });
402
+ expect(triggerSetToolStatus).toHaveBeenCalledWith('call_8', expect.objectContaining({
403
+ content: triggerError,
404
+ error: triggerError,
405
+ isLoading: false
406
+ }));
407
+ expect(triggerResult.content).toBe(`Error while calling tool: ${triggerError}`);
408
+ expect(triggerSetToolStatus).not.toHaveBeenCalledWith('call_8', expect.objectContaining({
409
+ error: 'An error occurred while calling the tool'
410
+ }));
411
+ });
412
+ });
@@ -0,0 +1,7 @@
1
+ import { type Tool } from './shared';
2
+ export type WorkspaceMutationTarget = {
3
+ kind: 'script' | 'flow';
4
+ path?: string;
5
+ deployed?: boolean;
6
+ };
7
+ export declare function createWorkspaceMutationTools<T>(): Tool<T>[];
@@ -0,0 +1,239 @@
1
+ import { AzureTriggerService, GcpTriggerService, HttpTriggerService, KafkaTriggerService, MqttTriggerService, NatsTriggerService, PostgresTriggerService, ScheduleService, SqsTriggerService, WebsocketTriggerService } from '../../../gen';
2
+ import { createTriggerToolSchema, scheduleRequestSchema, triggerRequestSchemas } from './workspaceToolsZod.gen';
3
+ import { z } from 'zod';
4
+ import { createToolDef } from './shared';
5
+ import { emptyString } from '../../../utils';
6
+ const createScheduleToolSchema = scheduleRequestSchema.omit({ script_path: true, is_flow: true });
7
+ function getWorkspaceMutationTarget(helpers) {
8
+ return helpers?.getWorkspaceMutationTarget?.();
9
+ }
10
+ function getWorkspaceMutationTargetError(target) {
11
+ if (!target) {
12
+ return 'the script or flow needs to be deployed before doing this action';
13
+ }
14
+ if (!emptyString(target.path) && target.deployed) {
15
+ return undefined;
16
+ }
17
+ return `the ${target.kind} needs to be deployed before doing this action`;
18
+ }
19
+ function validateWorkspaceMutationTarget(helpers) {
20
+ return getWorkspaceMutationTargetError(getWorkspaceMutationTarget(helpers));
21
+ }
22
+ function requireWorkspaceMutationTarget(helpers) {
23
+ const target = getWorkspaceMutationTarget(helpers);
24
+ const error = getWorkspaceMutationTargetError(target);
25
+ if (error) {
26
+ throw new Error(error);
27
+ }
28
+ return target;
29
+ }
30
+ function getWorkspaceMutationTargetFields(helpers) {
31
+ const target = requireWorkspaceMutationTarget(helpers);
32
+ return {
33
+ script_path: target.path,
34
+ is_flow: target.kind === 'flow'
35
+ };
36
+ }
37
+ const createScheduleToolDef = createToolDef(createScheduleToolSchema, 'create_schedule', 'Create a schedule for the current script or flow.', { strict: false });
38
+ const createTriggerToolDef = createToolDef(createTriggerToolSchema, 'create_trigger', 'Create a trigger for the current script or flow.', { strict: false });
39
+ const triggerConfigs = {
40
+ http: {
41
+ label: 'HTTP trigger',
42
+ requestSchema: triggerRequestSchemas.http,
43
+ create: (data) => HttpTriggerService.createHttpTrigger(data)
44
+ },
45
+ websocket: {
46
+ label: 'WebSocket trigger',
47
+ requestSchema: triggerRequestSchemas.websocket,
48
+ create: (data) => WebsocketTriggerService.createWebsocketTrigger(data)
49
+ },
50
+ kafka: {
51
+ label: 'Kafka trigger',
52
+ requestSchema: triggerRequestSchemas.kafka,
53
+ create: (data) => KafkaTriggerService.createKafkaTrigger(data)
54
+ },
55
+ nats: {
56
+ label: 'NATS trigger',
57
+ requestSchema: triggerRequestSchemas.nats,
58
+ create: (data) => NatsTriggerService.createNatsTrigger(data)
59
+ },
60
+ postgres: {
61
+ label: 'Postgres trigger',
62
+ requestSchema: triggerRequestSchemas.postgres,
63
+ create: (data) => PostgresTriggerService.createPostgresTrigger(data)
64
+ },
65
+ mqtt: {
66
+ label: 'MQTT trigger',
67
+ requestSchema: triggerRequestSchemas.mqtt,
68
+ create: (data) => MqttTriggerService.createMqttTrigger(data)
69
+ },
70
+ sqs: {
71
+ label: 'SQS trigger',
72
+ requestSchema: triggerRequestSchemas.sqs,
73
+ create: (data) => SqsTriggerService.createSqsTrigger(data)
74
+ },
75
+ gcp: {
76
+ label: 'GCP Pub/Sub trigger',
77
+ requestSchema: triggerRequestSchemas.gcp,
78
+ create: (data) => GcpTriggerService.createGcpTrigger(data)
79
+ },
80
+ azure: {
81
+ label: 'Azure Event Grid trigger',
82
+ requestSchema: triggerRequestSchemas.azure,
83
+ create: (data) => AzureTriggerService.createAzureTrigger(data)
84
+ }
85
+ };
86
+ function formatPath(path) {
87
+ if (path.length === 0) {
88
+ return 'value';
89
+ }
90
+ return path
91
+ .map((part) => (typeof part === 'number' ? `[${part}]` : String(part)))
92
+ .join('.')
93
+ .replaceAll('.[', '[');
94
+ }
95
+ function formatZodError(error) {
96
+ return error.issues
97
+ .slice(0, 8)
98
+ .map((issue) => `${formatPath(issue.path)}: ${issue.message}`)
99
+ .join('; ');
100
+ }
101
+ function parseWithExplicitErrors(schema, value, label) {
102
+ const result = schema.safeParse(value);
103
+ if (!result.success) {
104
+ throw new Error(`${label} is invalid: ${formatZodError(result.error)}`);
105
+ }
106
+ return result.data;
107
+ }
108
+ function formatApiError(error) {
109
+ const bodyMessage = error?.body?.error?.message ??
110
+ error?.body?.message ??
111
+ (typeof error?.body?.error === 'string' ? error.body.error : undefined);
112
+ const body = bodyMessage ??
113
+ (typeof error?.body === 'string'
114
+ ? error.body
115
+ : error?.body !== undefined
116
+ ? stringifyErrorBody(error.body)
117
+ : undefined);
118
+ const message = body || error?.message || String(error);
119
+ return error?.status ? `HTTP ${error.status}: ${message}` : message;
120
+ }
121
+ function stringifyErrorBody(body) {
122
+ try {
123
+ return JSON.stringify(body);
124
+ }
125
+ catch {
126
+ return String(body);
127
+ }
128
+ }
129
+ function setToolError(toolCallbacks, toolId, error) {
130
+ const errorMessage = error instanceof Error ? error.message : String(error);
131
+ toolCallbacks.setToolStatus(toolId, {
132
+ content: errorMessage,
133
+ error: errorMessage,
134
+ isLoading: false,
135
+ needsConfirmation: false
136
+ });
137
+ return `Error while calling tool: ${errorMessage}`;
138
+ }
139
+ const createScheduleTool = {
140
+ def: createScheduleToolDef,
141
+ requiresConfirmation: true,
142
+ confirmationMessage: 'Create schedule',
143
+ showDetails: true,
144
+ validateBeforeConfirmation: ({ helpers }) => validateWorkspaceMutationTarget(helpers),
145
+ fn: async ({ args, workspace, helpers, toolCallbacks, toolId }) => {
146
+ try {
147
+ const requestBody = parseWithExplicitErrors(scheduleRequestSchema, {
148
+ ...args,
149
+ ...getWorkspaceMutationTargetFields(helpers)
150
+ }, 'Schedule');
151
+ toolCallbacks.setToolStatus(toolId, {
152
+ content: `Validating schedule "${requestBody.path}"...`
153
+ });
154
+ try {
155
+ await ScheduleService.previewSchedule({
156
+ requestBody: {
157
+ schedule: requestBody.schedule,
158
+ timezone: requestBody.timezone,
159
+ cron_version: requestBody.cron_version ?? undefined
160
+ }
161
+ });
162
+ }
163
+ catch (error) {
164
+ throw new Error(`Invalid schedule or timezone: ${formatApiError(error)}`);
165
+ }
166
+ toolCallbacks.setToolStatus(toolId, {
167
+ content: `Creating schedule "${requestBody.path}"...`
168
+ });
169
+ try {
170
+ const result = await ScheduleService.createSchedule({ workspace, requestBody });
171
+ const toolResult = {
172
+ success: true,
173
+ path: requestBody.path,
174
+ target_path: requestBody.script_path,
175
+ target_kind: requestBody.is_flow ? 'flow' : 'script',
176
+ backend_result: result
177
+ };
178
+ toolCallbacks.setToolStatus(toolId, {
179
+ content: `Created schedule "${requestBody.path}"`,
180
+ result: toolResult
181
+ });
182
+ return JSON.stringify(toolResult);
183
+ }
184
+ catch (error) {
185
+ throw new Error(`Failed to create schedule "${requestBody.path}": ${formatApiError(error)}`);
186
+ }
187
+ }
188
+ catch (error) {
189
+ return setToolError(toolCallbacks, toolId, error);
190
+ }
191
+ }
192
+ };
193
+ const createTriggerTool = {
194
+ def: createTriggerToolDef,
195
+ requiresConfirmation: true,
196
+ confirmationMessage: 'Create trigger',
197
+ showDetails: true,
198
+ validateBeforeConfirmation: ({ helpers }) => validateWorkspaceMutationTarget(helpers),
199
+ fn: async ({ args, workspace, helpers, toolCallbacks, toolId }) => {
200
+ try {
201
+ const parsedArgs = parseWithExplicitErrors(createTriggerToolSchema, args, 'Trigger');
202
+ const triggerConfig = triggerConfigs[parsedArgs.kind];
203
+ const requestBody = parseWithExplicitErrors(triggerConfig.requestSchema, {
204
+ ...parsedArgs.config,
205
+ path: parsedArgs.path,
206
+ ...getWorkspaceMutationTargetFields(helpers)
207
+ }, triggerConfig.label);
208
+ toolCallbacks.setToolStatus(toolId, {
209
+ content: `Creating ${triggerConfig.label} "${requestBody.path}"...`
210
+ });
211
+ try {
212
+ const result = await triggerConfig.create({ workspace, requestBody });
213
+ const toolResult = {
214
+ success: true,
215
+ kind: parsedArgs.kind,
216
+ path: requestBody.path,
217
+ target_path: requestBody.script_path,
218
+ target_kind: requestBody.is_flow ? 'flow' : 'script',
219
+ backend_result: result
220
+ };
221
+ toolCallbacks.setToolStatus(toolId, {
222
+ content: `Created ${triggerConfig.label} "${requestBody.path}"`,
223
+ result: toolResult
224
+ });
225
+ return JSON.stringify(toolResult);
226
+ }
227
+ catch (error) {
228
+ throw new Error(`Failed to create ${triggerConfig.label} "${requestBody.path}": ${formatApiError(error)}`);
229
+ }
230
+ }
231
+ catch (error) {
232
+ return setToolError(toolCallbacks, toolId, error);
233
+ }
234
+ }
235
+ };
236
+ const workspaceMutationTools = [createScheduleTool, createTriggerTool];
237
+ export function createWorkspaceMutationTools() {
238
+ return workspaceMutationTools;
239
+ }