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.
- package/package/components/ArgInput.svelte +2 -0
- package/package/components/AutoscalingConfigEditor.svelte +18 -4
- package/package/components/CompareWorkspaces.svelte +206 -157
- package/package/components/DatatableSchemaDiff.svelte +2 -2
- package/package/components/Dev.svelte +401 -85
- package/package/components/EditableSchemaForm.svelte +4 -0
- package/package/components/ErrorOrRecoveryHandler.svelte +2 -2
- package/package/components/FlowPreviewContent.svelte +32 -30
- package/package/components/FlowRestartButton.svelte +143 -61
- package/package/components/FlowRestartButton.svelte.d.ts +37 -0
- package/package/components/FlowStatusViewer.svelte +15 -1
- package/package/components/FlowStatusViewer.svelte.d.ts +10 -2
- package/package/components/FlowStatusViewerInner.svelte +1 -2
- package/package/components/FlowStatusViewerInner.svelte.d.ts +6 -2
- package/package/components/ForkConflictModal.svelte +57 -0
- package/package/components/ForkConflictModal.svelte.d.ts +3 -0
- package/package/components/GitRepoViewer.svelte +251 -97
- package/package/components/InputTransformSchemaForm.svelte +1 -1
- package/package/components/InstanceSettings.svelte +36 -16
- package/package/components/Login.svelte +113 -28
- package/package/components/Login.svelte.d.ts +1 -0
- package/package/components/Path.svelte +7 -1
- package/package/components/Path.svelte.d.ts +1 -1
- package/package/components/RunsPage.svelte +2 -1
- package/package/components/S3FilePickerInner.svelte +89 -89
- package/package/components/ScriptEditor.svelte +18 -5
- package/package/components/ShareModal.svelte.d.ts +1 -1
- package/package/components/apps/components/helpers/RunnableComponent.svelte.d.ts +3 -0
- package/package/components/apps/components/helpers/executeRunnable.js +2 -1
- package/package/components/apps/editor/AppReportsDrawerInner.svelte +1 -1
- package/package/components/apps/editor/appPolicy.js +2 -1
- package/package/components/apps/editor/commonAppUtils.d.ts +3 -0
- package/package/components/apps/editor/inlineScriptsPanel/CacheTtlPopup.svelte +1 -1
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +7 -0
- package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte +49 -0
- package/package/components/apps/editor/inlineScriptsPanel/TagPopup.svelte.d.ts +9 -0
- package/package/components/apps/inputType.d.ts +1 -0
- package/package/components/apps/sharedTypes.d.ts +1 -0
- package/package/components/auditLogs/AuditLogsFilters.svelte +8 -3
- package/package/components/common/fileUpload/S3ArgInput.svelte +12 -10
- package/package/components/common/fileUpload/S3ArgInput.svelte.d.ts +2 -0
- package/package/components/copilot/chat/AIChatDisplay.svelte +5 -36
- package/package/components/copilot/chat/AIChatInput.svelte +56 -47
- package/package/components/copilot/chat/AIChatManager.svelte.js +48 -46
- package/package/components/copilot/chat/ContextElementBadge.svelte +6 -4
- package/package/components/copilot/chat/app/core.d.ts +12 -20
- package/package/components/copilot/chat/app/core.js +103 -160
- package/package/components/copilot/chat/app/core.test.js +234 -9
- package/package/components/copilot/chat/context.js +44 -0
- package/package/components/copilot/chat/flow/FlowAIChat.svelte +5 -3
- package/package/components/copilot/chat/flow/core.d.ts +2 -1
- package/package/components/copilot/chat/flow/core.js +48 -21
- package/package/components/copilot/chat/flow/helperUtils.d.ts +5 -2
- package/package/components/copilot/chat/flow/helperUtils.js +33 -1
- package/package/components/copilot/chat/flow/helperUtils.test.js +116 -1
- package/package/components/copilot/chat/flow/openFlow.json +1 -1
- package/package/components/copilot/chat/flow/openFlowZod.gen.js +24 -0
- package/package/components/copilot/chat/script/core.js +3 -0
- package/package/components/copilot/chat/shared.d.ts +6 -0
- package/package/components/copilot/chat/shared.js +22 -1
- package/package/components/copilot/chat/shared.test.d.ts +1 -0
- package/package/components/copilot/chat/shared.test.js +412 -0
- package/package/components/copilot/chat/workspaceTools.d.ts +7 -0
- package/package/components/copilot/chat/workspaceTools.js +239 -0
- package/package/components/copilot/chat/workspaceToolsZod.gen.d.ts +1295 -0
- package/package/components/copilot/chat/workspaceToolsZod.gen.js +424 -0
- package/package/components/copilot/lib.js +3 -1
- package/package/components/copilot/lib.test.d.ts +1 -0
- package/package/components/copilot/lib.test.js +19 -0
- package/package/components/copilot/modelConfig.d.ts +3 -0
- package/package/components/copilot/modelConfig.js +10 -0
- package/package/components/flows/FlowProgressBar.svelte +5 -2
- package/package/components/flows/content/FlowModuleComponent.svelte +636 -599
- package/package/components/flows/conversations/FlowChatManager.svelte.js +21 -10
- package/package/components/flows/flowStateUtils.svelte.js +5 -1
- package/package/components/flows/map/FlowModuleSchemaMap.svelte +3 -2
- package/package/components/flows/map/FlowModuleSchemaMap.svelte.d.ts +1 -0
- package/package/components/git_sync/GitSyncContext.svelte.js +0 -2
- package/package/components/graph/FlowGraphV2.svelte +7 -3
- package/package/components/graph/FlowGraphV2.svelte.d.ts +1 -0
- package/package/components/graph/renderers/triggers/TriggersBadge.svelte +3 -0
- package/package/components/home/deploy_ui.js +1 -1
- package/package/components/icons/AzureIcon.svelte +12 -25
- package/package/components/icons/AzureIcon.svelte.d.ts +3 -2
- package/package/components/instanceSettings.js +24 -0
- package/package/components/mcp/McpScopeSelector.svelte +119 -9
- package/package/components/mcp/McpScopeSelector.svelte.d.ts +1 -0
- package/package/components/offboarding-utils.js +2 -0
- package/package/components/progressBar/ProgressBar.svelte +9 -5
- package/package/components/progressBar/ProgressBar.svelte.d.ts +1 -0
- package/package/components/raw_apps/DeleteAfterUsePopup.svelte +52 -0
- package/package/components/raw_apps/DeleteAfterUsePopup.svelte.d.ts +9 -0
- package/package/components/raw_apps/RawAppBackgroundRunner.svelte +5 -1
- package/package/components/raw_apps/RawAppEditor.svelte +159 -102
- package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +9 -3
- package/package/components/raw_apps/RawAppInlineScriptEditor.svelte.d.ts +2 -1
- package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +1 -0
- package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte.d.ts +1 -0
- package/package/components/raw_apps/RawAppInputsSpecEditor.svelte +48 -5
- package/package/components/raw_apps/RawAppSharedUiDrawer.svelte +129 -0
- package/package/components/raw_apps/RawAppSharedUiDrawer.svelte.d.ts +5 -0
- package/package/components/raw_apps/RawAppSidebar.svelte +12 -0
- package/package/components/raw_apps/dataTableRefUtils.d.ts +7 -0
- package/package/components/raw_apps/dataTableRefUtils.js +34 -0
- package/package/components/raw_apps/dataTableRefUtils.test.d.ts +1 -0
- package/package/components/raw_apps/dataTableRefUtils.test.js +29 -0
- package/package/components/raw_apps/rawAppPolicy.d.ts +1 -0
- package/package/components/raw_apps/rawAppPolicy.js +17 -2
- package/package/components/resources/resourceTypesFilter.d.ts +19 -0
- package/package/components/resources/resourceTypesFilter.js +21 -0
- package/package/components/restartFromStepPath.d.ts +39 -0
- package/package/components/restartFromStepPath.js +89 -0
- package/package/components/runs/JobDetailFieldConfig.d.ts +1 -0
- package/package/components/runs/JobDetailFieldConfig.js +57 -10
- package/package/components/runs/JobDetailHeader.svelte +24 -3
- package/package/components/runs/runsFilter.d.ts +1 -1
- package/package/components/schema/FlowPropertyEditor.svelte +30 -1
- package/package/components/schema/FlowPropertyEditor.svelte.d.ts +5 -2
- package/package/components/search/GlobalSearchModal.svelte +8 -1
- package/package/components/select/Select.svelte +1 -1
- package/package/components/settings/CreateToken.svelte +48 -77
- package/package/components/settings/EditTokenScopesModal.svelte +57 -0
- package/package/components/settings/EditTokenScopesModal.svelte.d.ts +10 -0
- package/package/components/settings/ScopesPicker.svelte +43 -0
- package/package/components/settings/ScopesPicker.svelte.d.ts +11 -0
- package/package/components/settings/TokensTable.svelte +51 -15
- package/package/components/sidebar/OperatorMenu.svelte +6 -0
- package/package/components/sidebar/SidebarContent.svelte +11 -1
- package/package/components/triggers/AddTriggersButton.svelte +6 -0
- package/package/components/triggers/CaptureWrapper.svelte +19 -1
- package/package/components/triggers/TriggerEditorToolbar.svelte.d.ts +1 -1
- package/package/components/triggers/TriggerModeToggle.svelte +36 -7
- package/package/components/triggers/TriggerModeToggle.svelte.d.ts +1 -1
- package/package/components/triggers/TriggerSuspendedJobsModal.svelte.d.ts +1 -1
- package/package/components/triggers/TriggersEditor.svelte +5 -1
- package/package/components/triggers/TriggersWrapper.svelte +10 -0
- package/package/components/triggers/azure/AzureCapture.svelte +41 -0
- package/package/components/triggers/azure/AzureCapture.svelte.d.ts +44 -0
- package/package/components/triggers/azure/AzureTriggerEditor.svelte +20 -0
- package/package/components/triggers/azure/AzureTriggerEditor.svelte.d.ts +9 -0
- package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte +301 -0
- package/package/components/triggers/azure/AzureTriggerEditorConfigSection.svelte.d.ts +16 -0
- package/package/components/triggers/azure/AzureTriggerEditorInner.svelte +422 -0
- package/package/components/triggers/azure/AzureTriggerEditorInner.svelte.d.ts +25 -0
- package/package/components/triggers/azure/AzureTriggerPanel.svelte +55 -0
- package/package/components/triggers/azure/AzureTriggerPanel.svelte.d.ts +10 -0
- package/{dist/sharedUtils/components/triggers/kafka → package/components/triggers/azure}/utils.d.ts +1 -1
- package/package/components/triggers/azure/utils.js +56 -0
- package/package/components/triggers/email/EmailTriggerEditorInner.svelte +2 -0
- package/package/components/triggers/gcp/GcpTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/http/RouteEditorInner.svelte +2 -0
- package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/mqtt/MqttTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/postgres/PostgresTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/schedules/ScheduleEditorInner.svelte +9 -3
- package/package/components/triggers/sqs/SqsTriggerEditorInner.svelte +9 -3
- package/package/components/triggers/triggers.svelte.d.ts +1 -0
- package/package/components/triggers/triggers.svelte.js +23 -1
- package/package/components/triggers/utils.js +20 -0
- package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +9 -3
- package/package/components/triggers.d.ts +1 -1
- package/package/components/useNestedRestartState.svelte.d.ts +56 -0
- package/package/components/useNestedRestartState.svelte.js +320 -0
- package/package/components/workspaceSettings/SharedUiSettings.svelte +175 -0
- package/package/components/workspaceSettings/SharedUiSettings.svelte.d.ts +3 -0
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/schemas.gen.d.ts +294 -24
- package/package/gen/schemas.gen.js +297 -25
- package/package/gen/services.gen.d.ts +247 -4
- package/package/gen/services.gen.js +498 -7
- package/package/gen/types.gen.d.ts +990 -37
- package/package/hubPaths.json +2 -5
- package/package/infer.d.ts +1 -1
- package/package/infer.js +37 -51
- package/package/mcpEndpointTools.js +60 -4
- package/package/script_helpers.js +17 -0
- package/package/stores.d.ts +7 -0
- package/package/stores.js +6 -1
- package/package/system_prompts/index.d.ts +1 -0
- package/package/system_prompts/index.js +8 -0
- package/package/system_prompts/prompts.d.ts +16 -13
- package/package/system_prompts/prompts.js +653 -43
- package/package/templates/ci_test_bun.ts.template +8 -0
- package/package/templates/ci_test_python.py.template +8 -0
- package/package/utils/forkConflict.d.ts +26 -0
- package/package/utils/forkConflict.js +56 -0
- package/package/utils_deployable.d.ts +164 -121
- package/package/utils_deployable.js +61 -11
- package/package/utils_workspace_deploy.js +3 -1
- package/package.json +28 -4
- package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +0 -2
- package/dist/sharedUtils/base.d.ts +0 -1
- package/dist/sharedUtils/cloud.d.ts +0 -1
- package/dist/sharedUtils/common.d.ts +0 -111
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +0 -5
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +0 -5
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +0 -5
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +0 -13
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +0 -11
- package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +0 -95
- package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +0 -6
- package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +0 -7
- package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +0 -33
- package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +0 -10
- package/dist/sharedUtils/components/apps/editor/component/components.d.ts +0 -5371
- package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +0 -3
- package/dist/sharedUtils/components/apps/editor/component/index.d.ts +0 -3
- package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +0 -7
- package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +0 -3
- package/dist/sharedUtils/components/apps/gridUtils.d.ts +0 -14
- package/dist/sharedUtils/components/apps/inputType.d.ts +0 -178
- package/dist/sharedUtils/components/apps/rx.d.ts +0 -29
- package/dist/sharedUtils/components/apps/sharedTypes.d.ts +0 -21
- package/dist/sharedUtils/components/apps/types.d.ts +0 -274
- package/dist/sharedUtils/components/assets/lib.d.ts +0 -25
- package/dist/sharedUtils/components/common/alert/model.d.ts +0 -2
- package/dist/sharedUtils/components/common/badge/model.d.ts +0 -8
- package/dist/sharedUtils/components/common/button/model.d.ts +0 -45
- package/dist/sharedUtils/components/common/fileInput/model.d.ts +0 -1
- package/dist/sharedUtils/components/common/index.d.ts +0 -24
- package/dist/sharedUtils/components/common/skeleton/model.d.ts +0 -21
- package/dist/sharedUtils/components/dbTypes.d.ts +0 -14
- package/dist/sharedUtils/components/diff_drawer.d.ts +0 -26
- package/dist/sharedUtils/components/ducklake.d.ts +0 -1
- package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +0 -7
- package/dist/sharedUtils/components/icons/index.d.ts +0 -101
- package/dist/sharedUtils/components/random_positive_adjetive.d.ts +0 -1
- package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +0 -10
- package/dist/sharedUtils/components/raw_apps/utils.d.ts +0 -15
- package/dist/sharedUtils/components/triggers/email/utils.d.ts +0 -4
- package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/http/utils.d.ts +0 -11
- package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/nats/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +0 -8
- package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +0 -32
- package/dist/sharedUtils/components/triggers/utils.d.ts +0 -80
- package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +0 -2
- package/dist/sharedUtils/components/triggers.d.ts +0 -20
- package/dist/sharedUtils/gen/core/ApiError.d.ts +0 -10
- package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +0 -13
- package/dist/sharedUtils/gen/core/ApiResult.d.ts +0 -7
- package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +0 -26
- package/dist/sharedUtils/gen/core/OpenAPI.d.ts +0 -27
- package/dist/sharedUtils/gen/core/request.d.ts +0 -29
- package/dist/sharedUtils/gen/index.d.ts +0 -6
- package/dist/sharedUtils/gen/schemas.gen.d.ts +0 -7036
- package/dist/sharedUtils/gen/services.gen.d.ts +0 -6047
- package/dist/sharedUtils/gen/types.gen.d.ts +0 -21881
- package/dist/sharedUtils/history.svelte.d.ts +0 -9
- package/dist/sharedUtils/hub.d.ts +0 -49
- package/dist/sharedUtils/jsr.json +0 -6
- package/dist/sharedUtils/lib.d.ts +0 -5
- package/dist/sharedUtils/lib.es.js +0 -1588
- package/dist/sharedUtils/package.json +0 -12
- package/dist/sharedUtils/schema.d.ts +0 -3
- package/dist/sharedUtils/stores.d.ts +0 -97
- package/dist/sharedUtils/svelte5Utils.svelte.d.ts +0 -80
- package/dist/sharedUtils/toast.d.ts +0 -8
- package/dist/sharedUtils/utils.d.ts +0 -265
- package/package/components/copilot/chat/flow/openFlowZod.js +0 -24
- /package/package/components/copilot/chat/flow/{openFlowZod.d.ts → openFlowZod.gen.d.ts} +0 -0
|
@@ -29,16 +29,6 @@ The preprocessor receives a single parameter called \`event\`.
|
|
|
29
29
|
`;
|
|
30
30
|
export const FLOW_BASE = `# Windmill Flow Building Guide
|
|
31
31
|
|
|
32
|
-
## CLI Commands
|
|
33
|
-
|
|
34
|
-
Create a folder ending with \`__flow\` and add a \`flow.yaml\` file with the flow definition.
|
|
35
|
-
For rawscript modules, use \`!inline path/to/script.ts\` for the content key. Inline script files should NOT include \`.inline_script.\` in their names (e.g. use \`a.ts\`, not \`a.inline_script.ts\`).
|
|
36
|
-
After writing, tell the user they can run:
|
|
37
|
-
- \`wmill generate-metadata\` - Generate lock files for the flow you modified
|
|
38
|
-
- \`wmill sync push\` - Deploy to Windmill
|
|
39
|
-
|
|
40
|
-
Do NOT run these commands yourself. Instead, inform the user that they should run them.
|
|
41
|
-
|
|
42
32
|
## OpenFlow Schema
|
|
43
33
|
|
|
44
34
|
The OpenFlow schema (openflow.openapi.yaml) is the source of truth for flow structure. Refer to OPENFLOW_SCHEMA for the complete type definitions.
|
|
@@ -331,6 +321,185 @@ Reference a specific resource using \`$res:\` prefix:
|
|
|
331
321
|
}
|
|
332
322
|
\`\`\`
|
|
333
323
|
`;
|
|
324
|
+
export const WORKFLOW_AS_CODE_BASE = `# Windmill Workflow-as-Code Writing Guide
|
|
325
|
+
|
|
326
|
+
## Scope
|
|
327
|
+
|
|
328
|
+
Use this guide when writing or modifying Windmill Workflow-as-Code (WAC) scripts.
|
|
329
|
+
WAC is authored as a Windmill script and deployed with the normal script workflow. It is not an OpenFlow YAML flow.
|
|
330
|
+
|
|
331
|
+
Supported WAC authoring targets:
|
|
332
|
+
- TypeScript scripts that import from \`windmill-client\`
|
|
333
|
+
- Python 3 scripts that import from \`wmill\`
|
|
334
|
+
|
|
335
|
+
## File Shape
|
|
336
|
+
|
|
337
|
+
TypeScript:
|
|
338
|
+
|
|
339
|
+
\`\`\`typescript
|
|
340
|
+
import {
|
|
341
|
+
task,
|
|
342
|
+
taskScript,
|
|
343
|
+
taskFlow,
|
|
344
|
+
step,
|
|
345
|
+
sleep,
|
|
346
|
+
waitForApproval,
|
|
347
|
+
getResumeUrls,
|
|
348
|
+
parallel,
|
|
349
|
+
workflow,
|
|
350
|
+
} from "windmill-client";
|
|
351
|
+
|
|
352
|
+
const process = task(async (x: string): Promise<string> => {
|
|
353
|
+
return \`processed: \${x}\`;
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
export const main = workflow(async (x: string) => {
|
|
357
|
+
const result = await process(x);
|
|
358
|
+
return { result };
|
|
359
|
+
});
|
|
360
|
+
\`\`\`
|
|
361
|
+
|
|
362
|
+
Python:
|
|
363
|
+
|
|
364
|
+
\`\`\`python
|
|
365
|
+
from wmill import task, task_script, task_flow, step, sleep, wait_for_approval, get_resume_urls, parallel, workflow
|
|
366
|
+
|
|
367
|
+
@task()
|
|
368
|
+
async def process(x: str) -> str:
|
|
369
|
+
return f"processed: {x}"
|
|
370
|
+
|
|
371
|
+
@workflow
|
|
372
|
+
async def main(x: str):
|
|
373
|
+
result = await process(x)
|
|
374
|
+
return {"result": result}
|
|
375
|
+
\`\`\`
|
|
376
|
+
|
|
377
|
+
Rules:
|
|
378
|
+
- Do not call \`main\`.
|
|
379
|
+
- TypeScript should export the workflow entrypoint, preferably \`export const main = workflow(async (...) => { ... })\`.
|
|
380
|
+
- Python must use \`@workflow\` on an async top-level function, usually \`main\`.
|
|
381
|
+
- Define task functions and \`taskScript\`/\`task_script\` or \`taskFlow\`/\`task_flow\` assignments at module top level with stable names.
|
|
382
|
+
- Use the exact SDK names. Do not alias \`workflow\`, \`task\`, \`taskScript\`, \`taskFlow\`, \`step\`, \`sleep\`, \`waitForApproval\`, \`task_script\`, \`task_flow\`, or \`wait_for_approval\`; the WAC parser recognizes these names directly.
|
|
383
|
+
|
|
384
|
+
## Checkpoint And Replay Model
|
|
385
|
+
|
|
386
|
+
The parent workflow may rerun from the top after any suspension, retry, approval, or child task completion. Completed durable steps are replayed from the checkpoint.
|
|
387
|
+
|
|
388
|
+
Put every side effect or non-deterministic value behind a durable WAC boundary:
|
|
389
|
+
- Use \`task()\` / \`@task()\` for substantial work that should run as its own child job.
|
|
390
|
+
- Use \`taskScript()\` / \`task_script()\` for an existing script or a relative module file.
|
|
391
|
+
- Use \`taskFlow()\` / \`task_flow()\` for an existing Windmill flow.
|
|
392
|
+
- Use \`step(name, fn)\` for lightweight inline work whose result must be checkpointed.
|
|
393
|
+
- Use \`sleep(seconds)\` for server-side sleeps that do not hold a worker.
|
|
394
|
+
- Use \`waitForApproval()\` / \`wait_for_approval()\` for external approval suspension.
|
|
395
|
+
|
|
396
|
+
Never put API calls, database writes, notifications, random values, timestamps, or irreversible changes directly in the top-level workflow body. The workflow body can be rerun. Put those operations in a task or in \`step()\`.
|
|
397
|
+
|
|
398
|
+
Branching on task or step results is safe because those results are checkpointed. Branching on current time, random data, environment reads, or external state is unsafe unless the value is first captured with \`step()\`.
|
|
399
|
+
|
|
400
|
+
## Tasks
|
|
401
|
+
|
|
402
|
+
Use \`task()\` / \`@task()\` for inline functions that become workflow steps:
|
|
403
|
+
|
|
404
|
+
\`\`\`typescript
|
|
405
|
+
const enrich = task(async (customerId: string) => {
|
|
406
|
+
return await fetchCustomer(customerId);
|
|
407
|
+
});
|
|
408
|
+
\`\`\`
|
|
409
|
+
|
|
410
|
+
\`\`\`python
|
|
411
|
+
@task(timeout=600, tag="etl")
|
|
412
|
+
async def enrich(customer_id: str):
|
|
413
|
+
return await fetch_customer(customer_id)
|
|
414
|
+
\`\`\`
|
|
415
|
+
|
|
416
|
+
In TypeScript, prefer assigning each task to a named top-level const. In Python, prefer top-level async functions decorated with \`@task()\` or \`@task\`.
|
|
417
|
+
|
|
418
|
+
For existing scripts:
|
|
419
|
+
|
|
420
|
+
\`\`\`typescript
|
|
421
|
+
const helper = taskScript("./helper.ts");
|
|
422
|
+
const existing = taskScript("f/data/extract", { timeout: 600 });
|
|
423
|
+
const value = await helper({ input: x });
|
|
424
|
+
\`\`\`
|
|
425
|
+
|
|
426
|
+
\`\`\`python
|
|
427
|
+
helper = task_script("./helper.py")
|
|
428
|
+
existing = task_script("f/data/extract", timeout=600)
|
|
429
|
+
value = await helper(input=x)
|
|
430
|
+
\`\`\`
|
|
431
|
+
|
|
432
|
+
For existing flows:
|
|
433
|
+
|
|
434
|
+
\`\`\`typescript
|
|
435
|
+
const pipeline = taskFlow("f/etl/pipeline");
|
|
436
|
+
const output = await pipeline({ input: data });
|
|
437
|
+
\`\`\`
|
|
438
|
+
|
|
439
|
+
\`\`\`python
|
|
440
|
+
pipeline = task_flow("f/etl/pipeline")
|
|
441
|
+
output = await pipeline(input=data)
|
|
442
|
+
\`\`\`
|
|
443
|
+
|
|
444
|
+
## Inline Steps
|
|
445
|
+
|
|
446
|
+
Use \`step()\` for lightweight inline values that must not change during replay:
|
|
447
|
+
|
|
448
|
+
\`\`\`typescript
|
|
449
|
+
const urls = await step("get_urls", () => getResumeUrls());
|
|
450
|
+
const startedAt = await step("started_at", () => new Date().toISOString());
|
|
451
|
+
\`\`\`
|
|
452
|
+
|
|
453
|
+
\`\`\`python
|
|
454
|
+
urls = await step("get_urls", lambda: get_resume_urls())
|
|
455
|
+
\`\`\`
|
|
456
|
+
|
|
457
|
+
Use stable, descriptive step names. Do not generate step names dynamically.
|
|
458
|
+
|
|
459
|
+
## Parallelism
|
|
460
|
+
|
|
461
|
+
To run independent work in parallel, start task promises/coroutines before awaiting them together:
|
|
462
|
+
|
|
463
|
+
\`\`\`typescript
|
|
464
|
+
const [a, b] = await Promise.all([process("a"), process("b")]);
|
|
465
|
+
const many = await parallel(items, process, { concurrency: 5 });
|
|
466
|
+
\`\`\`
|
|
467
|
+
|
|
468
|
+
\`\`\`python
|
|
469
|
+
import asyncio
|
|
470
|
+
|
|
471
|
+
a, b = await asyncio.gather(process("a"), process("b"))
|
|
472
|
+
many = await parallel(items, process, concurrency=5)
|
|
473
|
+
\`\`\`
|
|
474
|
+
|
|
475
|
+
Only parallelize independent steps. Do not read the result of a task before it is awaited.
|
|
476
|
+
|
|
477
|
+
## Approvals
|
|
478
|
+
|
|
479
|
+
Generate resume URLs inside \`step()\` before sending them:
|
|
480
|
+
|
|
481
|
+
\`\`\`typescript
|
|
482
|
+
const urls = await step("get_urls", () => getResumeUrls());
|
|
483
|
+
await step("notify", () => sendApprovalEmail(urls.approvalPage));
|
|
484
|
+
const approval = await waitForApproval({ timeout: 3600 });
|
|
485
|
+
\`\`\`
|
|
486
|
+
|
|
487
|
+
\`\`\`python
|
|
488
|
+
urls = await step("get_urls", lambda: get_resume_urls())
|
|
489
|
+
await step("notify", lambda: send_approval_email(urls["approvalPage"]))
|
|
490
|
+
approval = await wait_for_approval(timeout=3600)
|
|
491
|
+
\`\`\`
|
|
492
|
+
|
|
493
|
+
\`selfApproval: false\` and \`self_approval=False\` are Enterprise-only approval behavior. Do not use them unless the user asks for that behavior.
|
|
494
|
+
|
|
495
|
+
## Error Handling
|
|
496
|
+
|
|
497
|
+
Let task errors fail the workflow unless the user asks for recovery logic.
|
|
498
|
+
|
|
499
|
+
Python: \`except Exception\` is safe around WAC calls because internal suspension inherits from \`BaseException\`. Avoid bare \`except:\` in workflow code. If the user asks for recovery logic around failed child work, catch \`TaskError\` from \`wmill\` for task failures.
|
|
500
|
+
|
|
501
|
+
TypeScript: avoid broad \`try/catch\` around WAC SDK calls. The SDK uses an internal suspension error during initial dispatch; catching it can break workflow suspension. If a broad catch is unavoidable, rethrow internal suspension errors before handling business errors.
|
|
502
|
+
`;
|
|
334
503
|
export const FLOW_CHAT_SPECIAL_MODULES = `## Special Modules
|
|
335
504
|
|
|
336
505
|
- Use \`set_preprocessor_module\` to add, replace, or remove the top-level \`value.preprocessor_module\`
|
|
@@ -1598,6 +1767,223 @@ async def parallel(items, fn, concurrency: Optional[int] = None)
|
|
|
1598
1767
|
# offset: Message offset to commit (from event['offset'])
|
|
1599
1768
|
def commit_kafka_offsets(trigger_path: str, topic: str, partition: int, offset: int) -> None
|
|
1600
1769
|
|
|
1770
|
+
`;
|
|
1771
|
+
export const WAC_SDK_TYPESCRIPT = `## TypeScript Workflow-as-Code API (windmill-client)
|
|
1772
|
+
|
|
1773
|
+
Import: \`import { workflow, task, taskScript, taskFlow, step, sleep, waitForApproval, getResumeUrls, parallel } from "windmill-client"\`
|
|
1774
|
+
|
|
1775
|
+
\`\`\`typescript
|
|
1776
|
+
export interface TaskOptions {
|
|
1777
|
+
timeout?: number;
|
|
1778
|
+
tag?: string;
|
|
1779
|
+
cache_ttl?: number;
|
|
1780
|
+
priority?: number;
|
|
1781
|
+
concurrency_limit?: number;
|
|
1782
|
+
concurrency_key?: string;
|
|
1783
|
+
concurrency_time_window_s?: number;
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
/**
|
|
1787
|
+
* Get URLs needed for resuming a flow after this step
|
|
1788
|
+
* @param approver approver name
|
|
1789
|
+
* @param flowLevel if true, generate resume URLs for the parent flow instead of the specific step.
|
|
1790
|
+
* This allows pre-approvals that can be consumed by any later suspend step in the same flow.
|
|
1791
|
+
* @returns approval page UI URL, resume and cancel API URLs for resuming the flow
|
|
1792
|
+
*/
|
|
1793
|
+
export async function getResumeUrls(approver?: string, flowLevel?: boolean): Promise<{ approvalPage: string; resume: string; cancel: string; }>
|
|
1794
|
+
|
|
1795
|
+
/**
|
|
1796
|
+
* Wrap an async function as a workflow task.
|
|
1797
|
+
*
|
|
1798
|
+
* @example
|
|
1799
|
+
* const extract_data = task(async (url: string) => { ... });
|
|
1800
|
+
* const run_external = task("f/external_script", async (x: number) => { ... });
|
|
1801
|
+
*
|
|
1802
|
+
* Inside a \`workflow()\`, calling a task dispatches it as a step.
|
|
1803
|
+
* Outside a workflow, the function body executes directly.
|
|
1804
|
+
*/
|
|
1805
|
+
export function task<T extends (...args: any[]) => Promise<any>>(fnOrPath: T | string, maybeFnOrOptions?: T | TaskOptions, maybeOptions?: TaskOptions,): T
|
|
1806
|
+
|
|
1807
|
+
/**
|
|
1808
|
+
* Create a task that dispatches to a separate Windmill script.
|
|
1809
|
+
*
|
|
1810
|
+
* @example
|
|
1811
|
+
* const extract = taskScript("f/data/extract");
|
|
1812
|
+
* // inside workflow: await extract({ url: "https://..." })
|
|
1813
|
+
*/
|
|
1814
|
+
export function taskScript(path: string, options?: TaskOptions): (...args: any[]) => PromiseLike<any>
|
|
1815
|
+
|
|
1816
|
+
/**
|
|
1817
|
+
* Create a task that dispatches to a separate Windmill flow.
|
|
1818
|
+
*
|
|
1819
|
+
* @example
|
|
1820
|
+
* const pipeline = taskFlow("f/etl/pipeline");
|
|
1821
|
+
* // inside workflow: await pipeline({ input: data })
|
|
1822
|
+
*/
|
|
1823
|
+
export function taskFlow(path: string, options?: TaskOptions): (...args: any[]) => PromiseLike<any>
|
|
1824
|
+
|
|
1825
|
+
/**
|
|
1826
|
+
* Mark an async function as a workflow-as-code entry point.
|
|
1827
|
+
*
|
|
1828
|
+
* The function must be **deterministic**: given the same inputs it must call
|
|
1829
|
+
* tasks in the same order on every replay. Branching on task results is fine
|
|
1830
|
+
* (results are replayed from checkpoint), but branching on external state
|
|
1831
|
+
* (current time, random values, external API calls) must use \`step()\` to
|
|
1832
|
+
* checkpoint the value so replays see the same result.
|
|
1833
|
+
*/
|
|
1834
|
+
export function workflow<T>(fn: (...args: any[]) => Promise<T>)
|
|
1835
|
+
|
|
1836
|
+
export async function step<T>(name: string, fn: () => T | Promise<T>): Promise<T>
|
|
1837
|
+
|
|
1838
|
+
export async function sleep(seconds: number): Promise<void>
|
|
1839
|
+
|
|
1840
|
+
/**
|
|
1841
|
+
* Suspend the workflow and wait for an external approval.
|
|
1842
|
+
*
|
|
1843
|
+
* Use \`getResumeUrls()\` (wrapped in \`step()\`) to obtain resume/cancel/approvalPage
|
|
1844
|
+
* URLs before calling this function.
|
|
1845
|
+
*
|
|
1846
|
+
* @example
|
|
1847
|
+
* const urls = await step("urls", () => getResumeUrls());
|
|
1848
|
+
* await step("notify", () => sendEmail(urls.approvalPage));
|
|
1849
|
+
* const { value, approver } = await waitForApproval({ timeout: 3600 });
|
|
1850
|
+
*/
|
|
1851
|
+
export function waitForApproval(options?: { timeout?: number; form?: object; selfApproval?: boolean; }): PromiseLike<{ value: any; approver: string; approved: boolean }>
|
|
1852
|
+
|
|
1853
|
+
/**
|
|
1854
|
+
* Process items in parallel with optional concurrency control.
|
|
1855
|
+
*
|
|
1856
|
+
* Each item is processed by calling \`fn(item)\`, which should be a task().
|
|
1857
|
+
* Items are dispatched in batches of \`concurrency\` (default: all at once).
|
|
1858
|
+
*
|
|
1859
|
+
* @example
|
|
1860
|
+
* const process = task(async (item: string) => { ... });
|
|
1861
|
+
* const results = await parallel(items, process, { concurrency: 5 });
|
|
1862
|
+
*/
|
|
1863
|
+
export async function parallel<T, R>(items: T[], fn: (item: T) => PromiseLike<R> | R, options?: { concurrency?: number },): Promise<R[]>
|
|
1864
|
+
\`\`\`
|
|
1865
|
+
`;
|
|
1866
|
+
export const WAC_SDK_PYTHON = `## Python Workflow-as-Code API (wmill)
|
|
1867
|
+
|
|
1868
|
+
Import: \`from wmill import workflow, task, task_script, task_flow, step, sleep, wait_for_approval, get_resume_urls, parallel, TaskError\`
|
|
1869
|
+
|
|
1870
|
+
\`\`\`python
|
|
1871
|
+
# Raised when a WAC task step failed.
|
|
1872
|
+
#
|
|
1873
|
+
# Attributes:
|
|
1874
|
+
# step_key: The checkpoint key of the failed step.
|
|
1875
|
+
# child_job_id: The UUID of the failed child job.
|
|
1876
|
+
# result: The error result from the child job.
|
|
1877
|
+
class TaskError(Exception):
|
|
1878
|
+
def __init__(self, message: str, *, step_key: str = '', child_job_id: str = '', result = None)
|
|
1879
|
+
|
|
1880
|
+
# Get URLs needed for resuming a flow after suspension.
|
|
1881
|
+
#
|
|
1882
|
+
# Args:
|
|
1883
|
+
# approver: Optional approver name
|
|
1884
|
+
# flow_level: If True, generate resume URLs for the parent flow instead of the
|
|
1885
|
+
# specific step. This allows pre-approvals that can be consumed by any later
|
|
1886
|
+
# suspend step in the same flow.
|
|
1887
|
+
#
|
|
1888
|
+
# Returns:
|
|
1889
|
+
# Dictionary with approvalPage, resume, and cancel URLs
|
|
1890
|
+
def get_resume_urls(approver: str = None, flow_level: bool = None) -> dict
|
|
1891
|
+
|
|
1892
|
+
# Decorator that marks a function as a workflow task.
|
|
1893
|
+
#
|
|
1894
|
+
# Works in both WAC v1 (sync, HTTP-based dispatch) and WAC v2
|
|
1895
|
+
# (async, checkpoint/replay) modes:
|
|
1896
|
+
#
|
|
1897
|
+
# - **v2 (inside @workflow)**: dispatches as a checkpoint step.
|
|
1898
|
+
# - **v1 (WM_JOB_ID set, no @workflow)**: dispatches via HTTP API.
|
|
1899
|
+
# - **Standalone**: executes the function body directly.
|
|
1900
|
+
#
|
|
1901
|
+
# Usage::
|
|
1902
|
+
#
|
|
1903
|
+
# @task
|
|
1904
|
+
# async def extract_data(url: str): ...
|
|
1905
|
+
#
|
|
1906
|
+
# @task(path="f/external_script", timeout=600, tag="gpu")
|
|
1907
|
+
# async def run_external(x: int): ...
|
|
1908
|
+
def task(_func = None, *, path: Optional[str] = None, tag: Optional[str] = None, timeout: Optional[int] = None, cache_ttl: Optional[int] = None, priority: Optional[int] = None, concurrency_limit: Optional[int] = None, concurrency_key: Optional[str] = None, concurrency_time_window_s: Optional[int] = None)
|
|
1909
|
+
|
|
1910
|
+
# Create a task that dispatches to a separate Windmill script.
|
|
1911
|
+
#
|
|
1912
|
+
# Usage::
|
|
1913
|
+
#
|
|
1914
|
+
# extract = task_script("f/data/extract", timeout=600)
|
|
1915
|
+
#
|
|
1916
|
+
# @workflow
|
|
1917
|
+
# async def main():
|
|
1918
|
+
# data = await extract(url="https://...")
|
|
1919
|
+
def task_script(path: str, *, timeout: Optional[int] = None, tag: Optional[str] = None, cache_ttl: Optional[int] = None, priority: Optional[int] = None, concurrency_limit: Optional[int] = None, concurrency_key: Optional[str] = None, concurrency_time_window_s: Optional[int] = None)
|
|
1920
|
+
|
|
1921
|
+
# Create a task that dispatches to a separate Windmill flow.
|
|
1922
|
+
#
|
|
1923
|
+
# Usage::
|
|
1924
|
+
#
|
|
1925
|
+
# pipeline = task_flow("f/etl/pipeline", priority=10)
|
|
1926
|
+
#
|
|
1927
|
+
# @workflow
|
|
1928
|
+
# async def main():
|
|
1929
|
+
# result = await pipeline(input=data)
|
|
1930
|
+
def task_flow(path: str, *, timeout: Optional[int] = None, tag: Optional[str] = None, cache_ttl: Optional[int] = None, priority: Optional[int] = None, concurrency_limit: Optional[int] = None, concurrency_key: Optional[str] = None, concurrency_time_window_s: Optional[int] = None)
|
|
1931
|
+
|
|
1932
|
+
# Decorator marking an async function as a workflow-as-code entry point.
|
|
1933
|
+
#
|
|
1934
|
+
# The function must be **deterministic**: given the same inputs it must call
|
|
1935
|
+
# tasks in the same order on every replay. Branching on task results is fine
|
|
1936
|
+
# (results are replayed from checkpoint), but branching on external state
|
|
1937
|
+
# (current time, random values, external API calls) must use \`\`step()\`\` to
|
|
1938
|
+
# checkpoint the value so replays see the same result.
|
|
1939
|
+
def workflow(func)
|
|
1940
|
+
|
|
1941
|
+
# Execute \`\`fn\`\` inline and checkpoint the result.
|
|
1942
|
+
#
|
|
1943
|
+
# On replay the cached value is returned without re-executing \`\`fn\`\`.
|
|
1944
|
+
# Use for lightweight deterministic operations (timestamps, random IDs,
|
|
1945
|
+
# config reads) that should not incur the overhead of a child job.
|
|
1946
|
+
async def step(name: str, fn)
|
|
1947
|
+
|
|
1948
|
+
# Server-side sleep — suspend the workflow for the given duration without holding a worker.
|
|
1949
|
+
#
|
|
1950
|
+
# Inside a @workflow, the parent job suspends and auto-resumes after \`\`seconds\`\`.
|
|
1951
|
+
# Outside a workflow, falls back to \`\`asyncio.sleep\`\`.
|
|
1952
|
+
async def sleep(seconds: int)
|
|
1953
|
+
|
|
1954
|
+
# Suspend the workflow and wait for an external approval.
|
|
1955
|
+
#
|
|
1956
|
+
# Use \`\`get_resume_urls()\`\` (wrapped in \`\`step()\`\`) to obtain
|
|
1957
|
+
# resume/cancel/approval URLs before calling this function.
|
|
1958
|
+
#
|
|
1959
|
+
# Returns a dict with \`\`value\`\` (form data), \`\`approver\`\`, and \`\`approved\`\`.
|
|
1960
|
+
#
|
|
1961
|
+
# Args:
|
|
1962
|
+
# timeout: Approval timeout in seconds (default 1800).
|
|
1963
|
+
# form: Optional form schema for the approval page.
|
|
1964
|
+
# self_approval: Whether the user who triggered the flow can approve it (default True).
|
|
1965
|
+
#
|
|
1966
|
+
# Example::
|
|
1967
|
+
#
|
|
1968
|
+
# urls = await step("urls", lambda: get_resume_urls())
|
|
1969
|
+
# await step("notify", lambda: send_email(urls["approvalPage"]))
|
|
1970
|
+
# result = await wait_for_approval(timeout=3600)
|
|
1971
|
+
async def wait_for_approval(timeout: int = 1800, form: dict | None = None, self_approval: bool = True) -> dict
|
|
1972
|
+
|
|
1973
|
+
# Process items in parallel with optional concurrency control.
|
|
1974
|
+
#
|
|
1975
|
+
# Each item is processed by calling \`\`fn(item)\`\`, which should be a @task.
|
|
1976
|
+
# Items are dispatched in batches of \`\`concurrency\`\` (default: all at once).
|
|
1977
|
+
#
|
|
1978
|
+
# Example::
|
|
1979
|
+
#
|
|
1980
|
+
# @task
|
|
1981
|
+
# async def process(item: str):
|
|
1982
|
+
# ...
|
|
1983
|
+
#
|
|
1984
|
+
# results = await parallel(items, process, concurrency=5)
|
|
1985
|
+
async def parallel(items, fn, *, concurrency: Optional[int] = None)
|
|
1986
|
+
\`\`\`
|
|
1601
1987
|
`;
|
|
1602
1988
|
export const DATATABLE_SDK_TYPESCRIPT = `## TypeScript Datatable API (windmill-client)
|
|
1603
1989
|
|
|
@@ -1747,7 +2133,7 @@ class SqlQuery:
|
|
|
1747
2133
|
`;
|
|
1748
2134
|
export const OPENFLOW_SCHEMA = `## OpenFlow Schema
|
|
1749
2135
|
|
|
1750
|
-
{"OpenFlow":{"type":"object","description":"Top-level flow definition containing metadata, configuration, and the flow structure","properties":{"summary":{"type":"string","description":"Short description of what this flow does"},"description":{"type":"string","description":"Detailed documentation for this flow"},"value":{"$ref":"#/components/schemas/FlowValue"},"schema":{"type":"object","description":"JSON Schema for flow inputs. Use this to define input parameters, their types, defaults, and validation. For resource inputs, set type to 'object' and format to 'resource-<type>' (e.g., 'resource-stripe')"},"on_behalf_of_email":{"type":"string","description":"The flow will be run with the permissions of the user with this email."}},"required":["summary","value"]},"FlowValue":{"type":"object","description":"The flow structure containing modules and optional preprocessor/failure handlers","properties":{"modules":{"type":"array","description":"Array of steps that execute in sequence. Each step can be a script, subflow, loop, or branch","items":{"$ref":"#/components/schemas/FlowModule"}},"failure_module":{"description":"Special module that executes when the flow fails. Receives error object with message, name, stack, and step_id. Must have id 'failure'. Only supports script/rawscript types","$ref":"#/components/schemas/FlowModule"},"preprocessor_module":{"description":"Special module that runs before the first step on external triggers. Must have id 'preprocessor'. Only supports script/rawscript types. Cannot reference other step results","$ref":"#/components/schemas/FlowModule"},"same_worker":{"type":"boolean","description":"If true, all steps run on the same worker for better performance"},"concurrent_limit":{"type":"number","description":"Maximum number of concurrent executions of this flow"},"concurrency_key":{"type":"string","description":"Expression to group concurrent executions (e.g., by user ID)"},"concurrency_time_window_s":{"type":"number","description":"Time window in seconds for concurrent_limit"},"debounce_delay_s":{"type":"integer","description":"Delay in seconds to debounce flow executions"},"debounce_key":{"type":"string","description":"Expression to group debounced executions"},"debounce_args_to_accumulate":{"type":"array","description":"Arguments to accumulate across debounced executions","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"Maximum total time in seconds that a job can be debounced"},"max_total_debounces_amount":{"type":"integer","description":"Maximum number of times a job can be debounced"},"skip_expr":{"type":"string","description":"JavaScript expression to conditionally skip the entire flow"},"cache_ttl":{"type":"number","description":"Cache duration in seconds for flow results"},"cache_ignore_s3_path":{"type":"boolean"},"delete_after_secs":{"type":"integer","description":"If set, delete the flow job's args, result and logs after this many seconds following job completion"},"flow_env":{"type":"object","description":"Environment variables available to all steps. Values can be strings, JSON values, or special references: '$var:path' (workspace variable) or '$res:path' (resource).","additionalProperties":{}},"priority":{"type":"number","description":"Execution priority (higher numbers run first)"},"early_return":{"type":"string","description":"JavaScript expression to return early from the flow"},"chat_input_enabled":{"type":"boolean","description":"Whether this flow accepts chat-style input"},"notes":{"type":"array","description":"Sticky notes attached to the flow","items":{"$ref":"#/components/schemas/FlowNote"}},"groups":{"type":"array","description":"Semantic groups of modules for organizational purposes","items":{"$ref":"#/components/schemas/FlowGroup"}}},"required":["modules"]},"Retry":{"type":"object","description":"Retry configuration for failed module executions","properties":{"constant":{"type":"object","description":"Retry with constant delay between attempts","properties":{"attempts":{"type":"integer","description":"Number of retry attempts"},"seconds":{"type":"integer","description":"Seconds to wait between retries"}}},"exponential":{"type":"object","description":"Retry with exponential backoff (delay doubles each time)","properties":{"attempts":{"type":"integer","description":"Number of retry attempts"},"multiplier":{"type":"integer","description":"Multiplier for exponential backoff"},"seconds":{"type":"integer","minimum":1,"description":"Initial delay in seconds"},"random_factor":{"type":"integer","minimum":0,"maximum":100,"description":"Random jitter percentage (0-100) to avoid thundering herd"}}},"retry_if":{"$ref":"#/components/schemas/RetryIf"}}},"FlowNote":{"type":"object","description":"A sticky note attached to a flow for documentation and annotation","properties":{"id":{"type":"string","description":"Unique identifier for the note"},"text":{"type":"string","description":"Content of the note"},"position":{"type":"object","description":"Position of the note in the flow editor","properties":{"x":{"type":"number","description":"X coordinate"},"y":{"type":"number","description":"Y coordinate"}},"required":["x","y"]},"size":{"type":"object","description":"Size of the note in the flow editor","properties":{"width":{"type":"number","description":"Width in pixels"},"height":{"type":"number","description":"Height in pixels"}},"required":["width","height"]},"color":{"type":"string","description":"Color of the note (e.g., \\"yellow\\", \\"#ffff00\\")"},"type":{"type":"string","enum":["free","group"],"description":"Type of note - 'free' for standalone notes, 'group' for notes that group other nodes"},"locked":{"type":"boolean","default":false,"description":"Whether the note is locked and cannot be edited or moved"},"contained_node_ids":{"type":"array","items":{"type":"string"},"description":"For group notes, the IDs of nodes contained within this group"}},"required":["id","text","color","type"]},"FlowGroup":{"type":"object","description":"A semantic group of flow modules for organizational purposes. Does not affect execution \\u2014 modules remain in their original position in the flow. Groups provide naming and collapsibility in the editor. Members are computed dynamically from all nodes on paths between start_id and end_id.","properties":{"summary":{"type":"string","description":"Display name for this group"},"note":{"type":"string","description":"Markdown note shown below the group header"},"autocollapse":{"type":"boolean","default":false,"description":"If true, this group is collapsed by default in the flow editor. UI hint only."},"start_id":{"type":"string","description":"ID of the first flow module in this group (topological entry point)"},"end_id":{"type":"string","description":"ID of the last flow module in this group (topological exit point)"},"color":{"type":"string","description":"Color for the group in the flow editor"}},"required":["start_id","end_id"]},"RetryIf":{"type":"object","description":"Conditional retry based on error or result","properties":{"expr":{"type":"string","description":"JavaScript expression that returns true to retry. Has access to 'result' and 'error' variables"}},"required":["expr"]},"StopAfterIf":{"type":"object","description":"Early termination condition for a module","properties":{"skip_if_stopped":{"type":"boolean","description":"If true, following steps are skipped when this condition triggers"},"expr":{"type":"string","description":"JavaScript expression evaluated after the module runs. Can use 'result' (step's result) or 'flow_input'. Return true to stop"},"error_message":{"type":"string","nullable":true,"description":"Custom error message when stopping with an error. Mutually exclusive with skip_if_stopped. If set to a non-empty string, the flow stops with this error. If empty string, a default error message is used. If null or omitted, no error is raised."}},"required":["expr"]},"FlowModule":{"type":"object","description":"A single step in a flow. Can be a script, subflow, loop, or branch","properties":{"id":{"type":"string","description":"Unique identifier for this step. Used to reference results via 'results.step_id'. Must be a valid identifier (alphanumeric, underscore, hyphen)"},"value":{"$ref":"#/components/schemas/FlowModuleValue"},"stop_after_if":{"description":"Early termination condition evaluated after this step completes","$ref":"#/components/schemas/StopAfterIf"},"stop_after_all_iters_if":{"description":"For loops only - early termination condition evaluated after all iterations complete","$ref":"#/components/schemas/StopAfterIf"},"skip_if":{"type":"object","description":"Conditionally skip this step based on previous results or flow inputs","properties":{"expr":{"type":"string","description":"JavaScript expression that returns true to skip. Can use 'flow_input' or 'results.<step_id>'"}},"required":["expr"]},"sleep":{"description":"Delay before executing this step (in seconds or as expression)","$ref":"#/components/schemas/InputTransform"},"cache_ttl":{"type":"number","description":"Cache duration in seconds for this step's results"},"cache_ignore_s3_path":{"type":"boolean"},"timeout":{"description":"Maximum execution time in seconds (static value or expression)","$ref":"#/components/schemas/InputTransform"},"delete_after_secs":{"type":"integer","description":"If set, delete the step's args, result and logs after this many seconds following job completion"},"summary":{"type":"string","description":"Short description of what this step does"},"mock":{"type":"object","description":"Mock configuration for testing without executing the actual step","properties":{"enabled":{"type":"boolean","description":"If true, return mock value instead of executing"},"return_value":{"description":"Value to return when mocked"}}},"suspend":{"type":"object","description":"Configuration for approval/resume steps that wait for user input","properties":{"required_events":{"type":"integer","description":"Number of approvals required before continuing"},"timeout":{"type":"integer","description":"Timeout in seconds before auto-continuing or canceling"},"resume_form":{"type":"object","description":"Form schema for collecting input when resuming","properties":{"schema":{"type":"object","description":"JSON Schema for the resume form"}}},"user_auth_required":{"type":"boolean","description":"If true, only authenticated users can approve"},"user_groups_required":{"description":"Expression or list of groups that can approve","$ref":"#/components/schemas/InputTransform"},"self_approval_disabled":{"type":"boolean","description":"If true, the user who started the flow cannot approve"},"hide_cancel":{"type":"boolean","description":"If true, hide the cancel button on the approval form"},"continue_on_disapprove_timeout":{"type":"boolean","description":"If true, continue flow on timeout instead of canceling"}}},"priority":{"type":"number","description":"Execution priority for this step (higher numbers run first)"},"continue_on_error":{"type":"boolean","description":"If true, flow continues even if this step fails"},"retry":{"description":"Retry configuration if this step fails","$ref":"#/components/schemas/Retry"},"debouncing":{"description":"Debounce configuration for this step (EE only)","type":"object","properties":{"debounce_delay_s":{"type":"integer","description":"Delay in seconds to debounce this step's executions across flow runs"},"debounce_key":{"type":"string","description":"Expression to group debounced executions. Supports $workspace and $args[name]. Default: $workspace/flow/<flow_path>-<step_id>"},"debounce_args_to_accumulate":{"type":"array","description":"Array-type arguments to accumulate across debounced executions","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"Maximum total time in seconds before forced execution"},"max_total_debounces_amount":{"type":"integer","description":"Maximum number of debounces before forced execution"}}}},"required":["value","id"]},"InputTransform":{"description":"Maps input parameters for a step. Can be a static value or a JavaScript expression that references previous results or flow inputs","oneOf":[{"$ref":"#/components/schemas/StaticTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"StaticTransform":{"type":"object","description":"Static value passed directly to the step. Use for hardcoded values or resource references like '$res:path/to/resource'","properties":{"value":{"description":"The static value. For resources, use format '$res:path/to/resource'"},"type":{"type":"string","enum":["static"]}},"required":["type"]},"JavascriptTransform":{"type":"object","description":"JavaScript expression evaluated at runtime. Can reference previous step results via 'results.step_id' or flow inputs via 'flow_input.property'. Inside loops, use 'flow_input.iter.value' for the current iteration value","properties":{"expr":{"type":"string","description":"JavaScript expression returning the value. Available variables - results (object with all previous step results), flow_input (flow inputs), flow_input.iter (in loops)"},"type":{"type":"string","enum":["javascript"]}},"required":["expr","type"]},"AiTransform":{"type":"object","description":"Value resolved by the AI runtime for this input. The AI engine decides how to satisfy the parameter.","properties":{"type":{"type":"string","enum":["ai"]}},"required":["type"]},"AIProviderKind":{"type":"string","description":"Supported AI provider types","enum":["openai","azure_openai","anthropic","mistral","deepseek","googleai","groq","openrouter","togetherai","customai","aws_bedrock"]},"ProviderConfig":{"type":"object","description":"Complete AI provider configuration with resource reference and model selection","properties":{"kind":{"$ref":"#/components/schemas/AIProviderKind"},"resource":{"type":"string","description":"Resource reference in format '$res:{resource_path}' pointing to provider credentials"},"model":{"type":"string","description":"Model identifier (e.g., 'gpt-4', 'claude-3-opus-20240229', 'gemini-pro')"}},"required":["kind","resource","model"]},"StaticProviderTransform":{"type":"object","description":"Static provider configuration passed directly to the AI agent","properties":{"value":{"$ref":"#/components/schemas/ProviderConfig"},"type":{"type":"string","enum":["static"]}},"required":["type","value"]},"ProviderTransform":{"description":"Provider configuration - can be static (ProviderConfig), JavaScript expression, or AI-determined","oneOf":[{"$ref":"#/components/schemas/StaticProviderTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticProviderTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"MemoryOff":{"type":"object","description":"No conversation memory/context","properties":{"kind":{"type":"string","enum":["off"]}},"required":["kind"]},"MemoryAuto":{"type":"object","description":"Automatic context management","properties":{"kind":{"type":"string","enum":["auto"]},"context_length":{"type":"integer","description":"Maximum number of messages to retain in context"},"memory_id":{"type":"string","description":"Identifier for persistent memory across agent invocations"}},"required":["kind"]},"MemoryMessage":{"type":"object","description":"A single message in conversation history","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"MemoryManual":{"type":"object","description":"Explicit message history","properties":{"kind":{"type":"string","enum":["manual"]},"messages":{"type":"array","items":{"$ref":"#/components/schemas/MemoryMessage"}}},"required":["kind","messages"]},"MemoryConfig":{"description":"Conversation memory configuration","oneOf":[{"$ref":"#/components/schemas/MemoryOff"},{"$ref":"#/components/schemas/MemoryAuto"},{"$ref":"#/components/schemas/MemoryManual"}],"discriminator":{"propertyName":"kind","mapping":{"off":"#/components/schemas/MemoryOff","auto":"#/components/schemas/MemoryAuto","manual":"#/components/schemas/MemoryManual"}}},"StaticMemoryTransform":{"type":"object","description":"Static memory configuration passed directly to the AI agent","properties":{"value":{"$ref":"#/components/schemas/MemoryConfig"},"type":{"type":"string","enum":["static"]}},"required":["type","value"]},"MemoryTransform":{"description":"Memory configuration - can be static (MemoryConfig), JavaScript expression, or AI-determined","oneOf":[{"$ref":"#/components/schemas/StaticMemoryTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticMemoryTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"FlowModuleValue":{"description":"The actual implementation of a flow step. Can be a script (inline or referenced), subflow, loop, branch, or special module type","oneOf":[{"$ref":"#/components/schemas/RawScript"},{"$ref":"#/components/schemas/PathScript"},{"$ref":"#/components/schemas/PathFlow"},{"$ref":"#/components/schemas/ForloopFlow"},{"$ref":"#/components/schemas/WhileloopFlow"},{"$ref":"#/components/schemas/BranchOne"},{"$ref":"#/components/schemas/BranchAll"},{"$ref":"#/components/schemas/Identity"},{"$ref":"#/components/schemas/AiAgent"}],"discriminator":{"propertyName":"type","mapping":{"rawscript":"#/components/schemas/RawScript","script":"#/components/schemas/PathScript","flow":"#/components/schemas/PathFlow","forloopflow":"#/components/schemas/ForloopFlow","whileloopflow":"#/components/schemas/WhileloopFlow","branchone":"#/components/schemas/BranchOne","branchall":"#/components/schemas/BranchAll","identity":"#/components/schemas/Identity","aiagent":"#/components/schemas/AiAgent"}}},"RawScript":{"type":"object","description":"Inline script with code defined directly in the flow. Use 'bun' as default language if unspecified. The script receives arguments from input_transforms","properties":{"input_transforms":{"type":"object","description":"Map of parameter names to their values (static or JavaScript expressions). These become the script's input arguments","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"content":{"type":"string","description":"The script source code. Should export a 'main' function"},"language":{"type":"string","description":"Programming language for this script","enum":["deno","bun","python3","go","bash","powershell","postgresql","mysql","bigquery","snowflake","mssql","oracledb","graphql","nativets","php","rust","ansible","csharp","nu","java","ruby","rlang","duckdb"]},"path":{"type":"string","description":"Optional path for saving this script"},"lock":{"type":"string","description":"Lock file content for dependencies"},"type":{"type":"string","enum":["rawscript"]},"tag":{"type":"string","description":"Worker group tag for execution routing"},"concurrent_limit":{"type":"number","description":"Maximum concurrent executions of this script"},"concurrency_time_window_s":{"type":"number","description":"Time window for concurrent_limit"},"custom_concurrency_key":{"type":"string","description":"Custom key for grouping concurrent executions"},"is_trigger":{"type":"boolean","description":"If true, this script is a trigger that can start the flow"},"assets":{"type":"array","description":"External resources this script accesses (S3 objects, resources, etc.)","items":{"type":"object","required":["path","kind"],"properties":{"path":{"type":"string","description":"Path to the asset"},"kind":{"type":"string","description":"Type of asset","enum":["s3object","resource","ducklake","datatable","volume"]},"access_type":{"type":"string","nullable":true,"description":"Access level for this asset","enum":["r","w","rw"]},"alt_access_type":{"type":"string","nullable":true,"description":"Alternative access level","enum":["r","w","rw"]}}}}},"required":["type","content","language","input_transforms"]},"PathScript":{"type":"object","description":"Reference to an existing script by path. Use this when calling a previously saved script instead of writing inline code","properties":{"input_transforms":{"type":"object","description":"Map of parameter names to their values (static or JavaScript expressions). These become the script's input arguments","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"path":{"type":"string","description":"Path to the script in the workspace (e.g., 'f/scripts/send_email')"},"hash":{"type":"string","description":"Optional specific version hash of the script to use"},"type":{"type":"string","enum":["script"]},"tag_override":{"type":"string","description":"Override the script's default worker group tag"},"is_trigger":{"type":"boolean","description":"If true, this script is a trigger that can start the flow"}},"required":["type","path","input_transforms"]},"PathFlow":{"type":"object","description":"Reference to an existing flow by path. Use this to call another flow as a subflow","properties":{"input_transforms":{"type":"object","description":"Map of parameter names to their values (static or JavaScript expressions). These become the subflow's input arguments","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"path":{"type":"string","description":"Path to the flow in the workspace (e.g., 'f/flows/process_user')"},"type":{"type":"string","enum":["flow"]}},"required":["type","path","input_transforms"]},"ForloopFlow":{"type":"object","description":"Executes nested modules in a loop over an iterator. Inside the loop, use 'flow_input.iter.value' to access the current iteration value, and 'flow_input.iter.index' for the index. Supports parallel execution for better performance on I/O-bound operations","properties":{"modules":{"type":"array","description":"Steps to execute for each iteration. These can reference the iteration value via 'flow_input.iter.value'","items":{"$ref":"#/components/schemas/FlowModule"}},"iterator":{"description":"JavaScript expression that returns an array to iterate over. Can reference 'results.step_id' or 'flow_input'","$ref":"#/components/schemas/InputTransform"},"skip_failures":{"type":"boolean","description":"If true, iteration failures don't stop the loop. Failed iterations return null"},"type":{"type":"string","enum":["forloopflow"]},"parallel":{"type":"boolean","description":"If true, iterations run concurrently (faster for I/O-bound operations). Use with parallelism to control concurrency"},"parallelism":{"description":"Maximum number of concurrent iterations when parallel=true. Limits resource usage. Can be static number or expression","$ref":"#/components/schemas/InputTransform"},"squash":{"type":"boolean"}},"required":["modules","iterator","skip_failures","type"]},"WhileloopFlow":{"type":"object","description":"Executes nested modules repeatedly while a condition is true. The loop checks the condition after each iteration. Use stop_after_if on modules to control loop termination","properties":{"modules":{"type":"array","description":"Steps to execute in each iteration. Use stop_after_if to control when the loop ends","items":{"$ref":"#/components/schemas/FlowModule"}},"skip_failures":{"type":"boolean","description":"If true, iteration failures don't stop the loop. Failed iterations return null"},"type":{"type":"string","enum":["whileloopflow"]},"parallel":{"type":"boolean","description":"If true, iterations run concurrently (use with caution in while loops)"},"parallelism":{"description":"Maximum number of concurrent iterations when parallel=true","$ref":"#/components/schemas/InputTransform"},"squash":{"type":"boolean"}},"required":["modules","skip_failures","type"]},"BranchOne":{"type":"object","description":"Conditional branching where only the first matching branch executes. Branches are evaluated in order, and the first one with a true expression runs. If no branches match, the default branch executes","properties":{"branches":{"type":"array","description":"Array of branches to evaluate in order. The first branch with expr evaluating to true executes","items":{"type":"object","properties":{"summary":{"type":"string","description":"Short description of this branch condition"},"expr":{"type":"string","description":"JavaScript expression that returns boolean. Can use 'results.step_id' or 'flow_input'. First true expr wins"},"modules":{"type":"array","description":"Steps to execute if this branch's expr is true","items":{"$ref":"#/components/schemas/FlowModule"}}},"required":["modules","expr"]}},"default":{"type":"array","description":"Steps to execute if no branch expressions match","items":{"$ref":"#/components/schemas/FlowModule"}},"type":{"type":"string","enum":["branchone"]}},"required":["branches","default","type"]},"BranchAll":{"type":"object","description":"Parallel branching where all branches execute simultaneously. Unlike BranchOne, all branches run regardless of conditions. Useful for executing independent tasks concurrently","properties":{"branches":{"type":"array","description":"Array of branches that all execute (either in parallel or sequentially)","items":{"type":"object","properties":{"summary":{"type":"string","description":"Short description of this branch's purpose"},"skip_failure":{"type":"boolean","description":"If true, failure in this branch doesn't fail the entire flow"},"modules":{"type":"array","description":"Steps to execute in this branch","items":{"$ref":"#/components/schemas/FlowModule"}}},"required":["modules"]}},"type":{"type":"string","enum":["branchall"]},"parallel":{"type":"boolean","description":"If true, all branches execute concurrently. If false, they execute sequentially"}},"required":["branches","type"]},"AgentTool":{"type":"object","description":"A tool available to an AI agent. Can be a flow module or an external MCP (Model Context Protocol) tool","properties":{"id":{"type":"string","description":"Unique identifier for this tool. Cannot contain spaces - use underscores instead (e.g., 'get_user_data' not 'get user data')"},"summary":{"type":"string","description":"Short description of what this tool does (shown to the AI)"},"value":{"$ref":"#/components/schemas/ToolValue"}},"required":["id","value"]},"ToolValue":{"description":"The implementation of a tool. Can be a flow module (script/flow) or an MCP tool reference","oneOf":[{"$ref":"#/components/schemas/FlowModuleTool"},{"$ref":"#/components/schemas/McpToolValue"},{"$ref":"#/components/schemas/WebsearchToolValue"}],"discriminator":{"propertyName":"tool_type","mapping":{"flowmodule":"#/components/schemas/FlowModuleTool","mcp":"#/components/schemas/McpToolValue","websearch":"#/components/schemas/WebsearchToolValue"}}},"FlowModuleTool":{"description":"A tool implemented as a flow module (script, flow, etc.). The AI can call this like any other flow module","allOf":[{"type":"object","properties":{"tool_type":{"type":"string","enum":["flowmodule"]}},"required":["tool_type"]},{"$ref":"#/components/schemas/FlowModuleValue"}]},"WebsearchToolValue":{"type":"object","description":"A tool implemented as a websearch tool. The AI can call this like any other websearch tool","properties":{"tool_type":{"type":"string","enum":["websearch"]}},"required":["tool_type"]},"McpToolValue":{"type":"object","description":"Reference to an external MCP (Model Context Protocol) tool. The AI can call tools from MCP servers","properties":{"tool_type":{"type":"string","enum":["mcp"]},"resource_path":{"type":"string","description":"Path to the MCP resource/server configuration"},"include_tools":{"type":"array","description":"Whitelist of specific tools to include from this MCP server","items":{"type":"string"}},"exclude_tools":{"type":"array","description":"Blacklist of tools to exclude from this MCP server","items":{"type":"string"}}},"required":["tool_type","resource_path"]},"AiAgent":{"type":"object","description":"AI agent step that can use tools to accomplish tasks. The agent receives inputs and can call any of its configured tools to complete the task","properties":{"input_transforms":{"type":"object","description":"Input parameters for the AI agent mapped to their values","properties":{"provider":{"$ref":"#/components/schemas/ProviderTransform"},"output_type":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Output format type.\\nValid values: 'text' (default) - plain text response, 'image' - image generation\\n"},"user_message":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"The user's prompt/message to the AI agent. Supports variable interpolation with flow.input syntax."},"system_prompt":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"System instructions that guide the AI's behavior, persona, and response style. Optional."},"streaming":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Boolean. If true, stream the AI response incrementally.\\nStreaming events include: token_delta, tool_call, tool_call_arguments, tool_execution, tool_result\\n"},"memory":{"$ref":"#/components/schemas/MemoryTransform"},"output_schema":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"JSON Schema object defining structured output format. Used when you need the AI to return data in a specific shape.\\nSupports standard JSON Schema properties: type, properties, required, items, enum, pattern, minLength, maxLength, minimum, maximum, etc.\\nExample: { type: 'object', properties: { name: { type: 'string' }, age: { type: 'integer' } }, required: ['name'] }\\n"},"user_attachments":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Array of file references (images or PDFs) for the AI agent.\\nFormat: Array<{ bucket: string, key: string }> - S3 object references\\nExample: [{ bucket: 'my-bucket', key: 'documents/report.pdf' }]\\n"},"max_completion_tokens":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Integer. Maximum number of tokens the AI will generate in its response.\\nRange: 1 to 4,294,967,295. Typical values: 256-4096 for most use cases.\\n"},"temperature":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Float. Controls randomness/creativity of responses.\\nRange: 0.0 to 2.0 (provider-dependent)\\n- 0.0 = deterministic, focused responses\\n- 0.7 = balanced (common default)\\n- 1.0+ = more creative/random\\n"}},"required":["provider","user_message","output_type"]},"tools":{"type":"array","description":"Array of tools the agent can use. The agent decides which tools to call based on the task","items":{"$ref":"#/components/schemas/AgentTool"}},"type":{"type":"string","enum":["aiagent"]},"parallel":{"type":"boolean","description":"If true, the agent can execute multiple tool calls in parallel"}},"required":["tools","type","input_transforms"]},"Identity":{"type":"object","description":"Pass-through module that returns its input unchanged. Useful for flow structure or as a placeholder","properties":{"type":{"type":"string","enum":["identity"]},"flow":{"type":"boolean","description":"If true, marks this as a flow identity (special handling)"}},"required":["type"]},"FlowStatus":{"type":"object","properties":{"step":{"type":"integer"},"modules":{"type":"array","items":{"$ref":"#/components/schemas/FlowStatusModule"}},"user_states":{"additionalProperties":true},"preprocessor_module":{"allOf":[{"$ref":"#/components/schemas/FlowStatusModule"}]},"failure_module":{"allOf":[{"$ref":"#/components/schemas/FlowStatusModule"},{"type":"object","properties":{"parent_module":{"type":"string"}}}]},"retry":{"type":"object","properties":{"fail_count":{"type":"integer"},"failed_jobs":{"type":"array","items":{"type":"string","format":"uuid"}}}}},"required":["step","modules","failure_module"]},"FlowStatusModule":{"type":"object","properties":{"type":{"type":"string","enum":["WaitingForPriorSteps","WaitingForEvents","WaitingForExecutor","InProgress","Success","Failure"]},"id":{"type":"string"},"job":{"type":"string","format":"uuid"},"count":{"type":"integer"},"progress":{"type":"integer"},"iterator":{"type":"object","properties":{"index":{"type":"integer"},"itered":{"type":"array","items":{}},"itered_len":{"type":"integer"},"args":{}}},"flow_jobs":{"type":"array","items":{"type":"string"}},"flow_jobs_success":{"type":"array","items":{"type":"boolean"}},"flow_jobs_duration":{"type":"object","properties":{"started_at":{"type":"array","items":{"type":"string"}},"duration_ms":{"type":"array","items":{"type":"integer"}}}},"branch_chosen":{"type":"object","properties":{"type":{"type":"string","enum":["branch","default"]},"branch":{"type":"integer"}},"required":["type"]},"branchall":{"type":"object","properties":{"branch":{"type":"integer"},"len":{"type":"integer"}},"required":["branch","len"]},"approvers":{"type":"array","items":{"type":"object","properties":{"resume_id":{"type":"integer"},"approver":{"type":"string"}},"required":["resume_id","approver"]}},"failed_retries":{"type":"array","items":{"type":"string","format":"uuid"}},"skipped":{"type":"boolean"},"agent_actions":{"type":"array","items":{"type":"object","oneOf":[{"type":"object","properties":{"job_id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"type":{"type":"string","enum":["tool_call"]},"module_id":{"type":"string"}},"required":["job_id","function_name","type","module_id"]},{"type":"object","properties":{"call_id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"resource_path":{"type":"string"},"type":{"type":"string","enum":["mcp_tool_call"]},"arguments":{"type":"object"}},"required":["call_id","function_name","resource_path","type"]},{"type":"object","properties":{"type":{"type":"string","enum":["web_search"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["message"]}},"required":["content","type"]}]}},"agent_actions_success":{"type":"array","items":{"type":"boolean"}}},"required":["type"]}}`;
|
|
2136
|
+
{"OpenFlow":{"type":"object","description":"Top-level flow definition containing metadata, configuration, and the flow structure","properties":{"summary":{"type":"string","description":"Short description of what this flow does"},"description":{"type":"string","description":"Detailed documentation for this flow"},"value":{"$ref":"#/components/schemas/FlowValue"},"schema":{"type":"object","description":"JSON Schema for flow inputs. Use this to define input parameters, their types, defaults, and validation. For resource inputs, set type to 'object' and format to 'resource-<type>' (e.g., 'resource-stripe')"},"on_behalf_of_email":{"type":"string","description":"The flow will be run with the permissions of the user with this email."}},"required":["summary","value"]},"FlowValue":{"type":"object","description":"The flow structure containing modules and optional preprocessor/failure handlers","properties":{"modules":{"type":"array","description":"Array of steps that execute in sequence. Each step can be a script, subflow, loop, or branch","items":{"$ref":"#/components/schemas/FlowModule"}},"failure_module":{"description":"Special module that executes when the flow fails. Receives error object with message, name, stack, and step_id. Must have id 'failure'. Only supports script/rawscript types","$ref":"#/components/schemas/FlowModule"},"preprocessor_module":{"description":"Special module that runs before the first step on external triggers. Must have id 'preprocessor'. Only supports script/rawscript types. Cannot reference other step results","$ref":"#/components/schemas/FlowModule"},"same_worker":{"type":"boolean","description":"If true, all steps run on the same worker for better performance"},"concurrent_limit":{"type":"number","description":"Maximum number of concurrent executions of this flow"},"concurrency_key":{"type":"string","description":"Expression to group concurrent executions (e.g., by user ID)"},"concurrency_time_window_s":{"type":"number","description":"Time window in seconds for concurrent_limit"},"debounce_delay_s":{"type":"integer","description":"Delay in seconds to debounce flow executions"},"debounce_key":{"type":"string","description":"Expression to group debounced executions"},"debounce_args_to_accumulate":{"type":"array","description":"Arguments to accumulate across debounced executions","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"Maximum total time in seconds that a job can be debounced"},"max_total_debounces_amount":{"type":"integer","description":"Maximum number of times a job can be debounced"},"skip_expr":{"type":"string","description":"JavaScript expression to conditionally skip the entire flow"},"cache_ttl":{"type":"number","description":"Cache duration in seconds for flow results"},"cache_ignore_s3_path":{"type":"boolean"},"delete_after_secs":{"type":"integer","description":"If set, delete the flow job's args, result and logs after this many seconds following job completion"},"flow_env":{"type":"object","description":"Environment variables available to all steps. Values can be strings, JSON values, or special references: '$var:path' (workspace variable) or '$res:path' (resource).","additionalProperties":{}},"priority":{"type":"number","description":"Execution priority (higher numbers run first)"},"early_return":{"type":"string","description":"JavaScript expression to return early from the flow"},"chat_input_enabled":{"type":"boolean","description":"Whether this flow accepts chat-style input"},"notes":{"type":"array","description":"Sticky notes attached to the flow","items":{"$ref":"#/components/schemas/FlowNote"}},"groups":{"type":"array","description":"Semantic groups of modules for organizational purposes","items":{"$ref":"#/components/schemas/FlowGroup"}}},"required":["modules"]},"Retry":{"type":"object","description":"Retry configuration for failed module executions","properties":{"constant":{"type":"object","description":"Retry with constant delay between attempts","properties":{"attempts":{"type":"integer","description":"Number of retry attempts"},"seconds":{"type":"integer","description":"Seconds to wait between retries"}}},"exponential":{"type":"object","description":"Retry with exponential backoff (delay doubles each time)","properties":{"attempts":{"type":"integer","description":"Number of retry attempts"},"multiplier":{"type":"integer","description":"Multiplier for exponential backoff"},"seconds":{"type":"integer","minimum":1,"description":"Initial delay in seconds"},"random_factor":{"type":"integer","minimum":0,"maximum":100,"description":"Random jitter percentage (0-100) to avoid thundering herd"}}},"retry_if":{"$ref":"#/components/schemas/RetryIf"}}},"FlowNote":{"type":"object","description":"A sticky note attached to a flow for documentation and annotation","properties":{"id":{"type":"string","description":"Unique identifier for the note"},"text":{"type":"string","description":"Content of the note"},"position":{"type":"object","description":"Position of the note in the flow editor","properties":{"x":{"type":"number","description":"X coordinate"},"y":{"type":"number","description":"Y coordinate"}},"required":["x","y"]},"size":{"type":"object","description":"Size of the note in the flow editor","properties":{"width":{"type":"number","description":"Width in pixels"},"height":{"type":"number","description":"Height in pixels"}},"required":["width","height"]},"color":{"type":"string","description":"Color of the note (e.g., \\"yellow\\", \\"#ffff00\\")"},"type":{"type":"string","enum":["free","group"],"description":"Type of note - 'free' for standalone notes, 'group' for notes that group other nodes"},"locked":{"type":"boolean","default":false,"description":"Whether the note is locked and cannot be edited or moved"},"contained_node_ids":{"type":"array","items":{"type":"string"},"description":"For group notes, the IDs of nodes contained within this group"}},"required":["id","text","color","type"]},"FlowGroup":{"type":"object","description":"A semantic group of flow modules for organizational purposes. Does not affect execution \\u2014 modules remain in their original position in the flow. Groups provide naming and collapsibility in the editor. Members are computed dynamically from all nodes on paths between start_id and end_id.","properties":{"summary":{"type":"string","description":"Display name for this group"},"note":{"type":"string","description":"Markdown note shown below the group header"},"autocollapse":{"type":"boolean","default":false,"description":"If true, this group is collapsed by default in the flow editor. UI hint only."},"start_id":{"type":"string","description":"ID of the first flow module in this group (topological entry point)"},"end_id":{"type":"string","description":"ID of the last flow module in this group (topological exit point)"},"color":{"type":"string","description":"Color for the group in the flow editor"}},"required":["start_id","end_id"]},"RetryIf":{"type":"object","description":"Conditional retry based on error or result","properties":{"expr":{"type":"string","description":"JavaScript expression that returns true to retry. Has access to 'result' and 'error' variables"}},"required":["expr"]},"StopAfterIf":{"type":"object","description":"Early termination condition for a module","properties":{"skip_if_stopped":{"type":"boolean","description":"If true, following steps are skipped when this condition triggers"},"expr":{"type":"string","description":"JavaScript expression evaluated after the module runs. Can use 'result' (step's result) or 'flow_input'. Return true to stop"},"error_message":{"type":"string","nullable":true,"description":"Custom error message when stopping with an error. Mutually exclusive with skip_if_stopped. If set to a non-empty string, the flow stops with this error. If empty string, a default error message is used. If null or omitted, no error is raised."}},"required":["expr"]},"FlowModule":{"type":"object","description":"A single step in a flow. Can be a script, subflow, loop, or branch","properties":{"id":{"type":"string","description":"Unique identifier for this step. Used to reference results via 'results.step_id'. Must be a valid identifier (alphanumeric, underscore, hyphen)"},"value":{"$ref":"#/components/schemas/FlowModuleValue"},"stop_after_if":{"description":"Early termination condition evaluated after this step completes","$ref":"#/components/schemas/StopAfterIf"},"stop_after_all_iters_if":{"description":"For loops only - early termination condition evaluated after all iterations complete","$ref":"#/components/schemas/StopAfterIf"},"skip_if":{"type":"object","description":"Conditionally skip this step based on previous results or flow inputs","properties":{"expr":{"type":"string","description":"JavaScript expression that returns true to skip. Can use 'flow_input' or 'results.<step_id>'"}},"required":["expr"]},"sleep":{"description":"Delay before executing this step (in seconds or as expression)","$ref":"#/components/schemas/InputTransform"},"cache_ttl":{"type":"number","description":"Cache duration in seconds for this step's results"},"cache_ignore_s3_path":{"type":"boolean"},"timeout":{"description":"Maximum execution time in seconds (static value or expression)","$ref":"#/components/schemas/InputTransform"},"delete_after_secs":{"type":"integer","description":"If set, delete the step's args, result and logs after this many seconds following job completion"},"summary":{"type":"string","description":"Short description of what this step does"},"mock":{"type":"object","description":"Mock configuration for testing without executing the actual step","properties":{"enabled":{"type":"boolean","description":"If true, return mock value instead of executing"},"return_value":{"description":"Value to return when mocked"}}},"suspend":{"type":"object","description":"Configuration for approval/resume steps that wait for user input","properties":{"required_events":{"type":"integer","description":"Number of approvals required before continuing"},"timeout":{"type":"integer","description":"Timeout in seconds before auto-continuing or canceling"},"resume_form":{"type":"object","description":"Form schema for collecting input when resuming","properties":{"schema":{"type":"object","description":"JSON Schema for the resume form"}}},"user_auth_required":{"type":"boolean","description":"If true, only authenticated users can approve"},"user_groups_required":{"description":"Expression or list of groups that can approve","$ref":"#/components/schemas/InputTransform"},"self_approval_disabled":{"type":"boolean","description":"If true, the user who started the flow cannot approve"},"hide_cancel":{"type":"boolean","description":"If true, hide the cancel button on the approval form"},"continue_on_disapprove_timeout":{"type":"boolean","description":"If true, continue flow on timeout instead of canceling"}}},"priority":{"type":"number","description":"Execution priority for this step (higher numbers run first)"},"continue_on_error":{"type":"boolean","description":"If true, flow continues even if this step fails"},"retry":{"description":"Retry configuration if this step fails","$ref":"#/components/schemas/Retry"},"debouncing":{"description":"Debounce configuration for this step (EE only)","type":"object","properties":{"debounce_delay_s":{"type":"integer","description":"Delay in seconds to debounce this step's executions across flow runs"},"debounce_key":{"type":"string","description":"Expression to group debounced executions. Supports $workspace and $args[name]. Default: $workspace/flow/<flow_path>-<step_id>"},"debounce_args_to_accumulate":{"type":"array","description":"Array-type arguments to accumulate across debounced executions","items":{"type":"string"}},"max_total_debouncing_time":{"type":"integer","description":"Maximum total time in seconds before forced execution"},"max_total_debounces_amount":{"type":"integer","description":"Maximum number of debounces before forced execution"}}}},"required":["value","id"]},"InputTransform":{"description":"Maps input parameters for a step. Can be a static value or a JavaScript expression that references previous results or flow inputs","oneOf":[{"$ref":"#/components/schemas/StaticTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"StaticTransform":{"type":"object","description":"Static value passed directly to the step. Use for hardcoded values or resource references like '$res:path/to/resource'","properties":{"value":{"description":"The static value. For resources, use format '$res:path/to/resource'"},"type":{"type":"string","enum":["static"]}},"required":["type"]},"JavascriptTransform":{"type":"object","description":"JavaScript expression evaluated at runtime. Can reference previous step results via 'results.step_id' or flow inputs via 'flow_input.property'. Inside loops, use 'flow_input.iter.value' for the current iteration value","properties":{"expr":{"type":"string","description":"JavaScript expression returning the value. Available variables - results (object with all previous step results), flow_input (flow inputs), flow_input.iter (in loops)"},"type":{"type":"string","enum":["javascript"]}},"required":["expr","type"]},"AiTransform":{"type":"object","description":"Value resolved by the AI runtime for this input. The AI engine decides how to satisfy the parameter.","properties":{"type":{"type":"string","enum":["ai"]}},"required":["type"]},"AIProviderKind":{"type":"string","description":"Supported AI provider types","enum":["openai","azure_openai","anthropic","mistral","deepseek","googleai","groq","openrouter","togetherai","customai","aws_bedrock"]},"ProviderConfig":{"type":"object","description":"Complete AI provider configuration with resource reference and model selection","properties":{"kind":{"$ref":"#/components/schemas/AIProviderKind"},"resource":{"type":"string","description":"Resource reference in format '$res:{resource_path}' pointing to provider credentials"},"model":{"type":"string","description":"Model identifier (e.g., 'gpt-4', 'claude-3-opus-20240229', 'gemini-pro')"}},"required":["kind","resource","model"]},"StaticProviderTransform":{"type":"object","description":"Static provider configuration passed directly to the AI agent","properties":{"value":{"$ref":"#/components/schemas/ProviderConfig"},"type":{"type":"string","enum":["static"]}},"required":["type","value"]},"ProviderTransform":{"description":"Provider configuration - can be static (ProviderConfig), JavaScript expression, or AI-determined","oneOf":[{"$ref":"#/components/schemas/StaticProviderTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticProviderTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"MemoryOff":{"type":"object","description":"No conversation memory/context","properties":{"kind":{"type":"string","enum":["off"]}},"required":["kind"]},"MemoryAuto":{"type":"object","description":"Automatic context management","properties":{"kind":{"type":"string","enum":["auto"]},"context_length":{"type":"integer","description":"Maximum number of messages to retain in context"},"memory_id":{"type":"string","description":"Identifier for persistent memory across agent invocations"}},"required":["kind"]},"MemoryMessage":{"type":"object","description":"A single message in conversation history","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}},"required":["role","content"]},"MemoryManual":{"type":"object","description":"Explicit message history","properties":{"kind":{"type":"string","enum":["manual"]},"messages":{"type":"array","items":{"$ref":"#/components/schemas/MemoryMessage"}}},"required":["kind","messages"]},"MemoryConfig":{"description":"Conversation memory configuration","oneOf":[{"$ref":"#/components/schemas/MemoryOff"},{"$ref":"#/components/schemas/MemoryAuto"},{"$ref":"#/components/schemas/MemoryManual"}],"discriminator":{"propertyName":"kind","mapping":{"off":"#/components/schemas/MemoryOff","auto":"#/components/schemas/MemoryAuto","manual":"#/components/schemas/MemoryManual"}}},"StaticMemoryTransform":{"type":"object","description":"Static memory configuration passed directly to the AI agent","properties":{"value":{"$ref":"#/components/schemas/MemoryConfig"},"type":{"type":"string","enum":["static"]}},"required":["type","value"]},"MemoryTransform":{"description":"Memory configuration - can be static (MemoryConfig), JavaScript expression, or AI-determined","oneOf":[{"$ref":"#/components/schemas/StaticMemoryTransform"},{"$ref":"#/components/schemas/JavascriptTransform"},{"$ref":"#/components/schemas/AiTransform"}],"discriminator":{"propertyName":"type","mapping":{"static":"#/components/schemas/StaticMemoryTransform","javascript":"#/components/schemas/JavascriptTransform","ai":"#/components/schemas/AiTransform"}}},"FlowModuleValue":{"description":"The actual implementation of a flow step. Can be a script (inline or referenced), subflow, loop, branch, or special module type","oneOf":[{"$ref":"#/components/schemas/RawScript"},{"$ref":"#/components/schemas/PathScript"},{"$ref":"#/components/schemas/PathFlow"},{"$ref":"#/components/schemas/ForloopFlow"},{"$ref":"#/components/schemas/WhileloopFlow"},{"$ref":"#/components/schemas/BranchOne"},{"$ref":"#/components/schemas/BranchAll"},{"$ref":"#/components/schemas/Identity"},{"$ref":"#/components/schemas/AiAgent"}],"discriminator":{"propertyName":"type","mapping":{"rawscript":"#/components/schemas/RawScript","script":"#/components/schemas/PathScript","flow":"#/components/schemas/PathFlow","forloopflow":"#/components/schemas/ForloopFlow","whileloopflow":"#/components/schemas/WhileloopFlow","branchone":"#/components/schemas/BranchOne","branchall":"#/components/schemas/BranchAll","identity":"#/components/schemas/Identity","aiagent":"#/components/schemas/AiAgent"}}},"RawScript":{"type":"object","description":"Inline script with code defined directly in the flow. Use 'bun' as default language if unspecified. The script receives arguments from input_transforms","properties":{"input_transforms":{"type":"object","description":"Map of parameter names to their values (static or JavaScript expressions). These become the script's input arguments","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"content":{"type":"string","description":"The script source code. Should export a 'main' function"},"language":{"type":"string","description":"Programming language for this script","enum":["deno","bun","python3","go","bash","powershell","postgresql","mysql","bigquery","snowflake","mssql","oracledb","graphql","nativets","php","rust","ansible","csharp","nu","java","ruby","rlang","duckdb"]},"path":{"type":"string","description":"Optional path for saving this script"},"lock":{"type":"string","description":"Lock file content for dependencies"},"type":{"type":"string","enum":["rawscript"]},"tag":{"type":"string","description":"Worker group tag for execution routing"},"concurrent_limit":{"type":"number","description":"Maximum concurrent executions of this script"},"concurrency_time_window_s":{"type":"number","description":"Time window for concurrent_limit"},"custom_concurrency_key":{"type":"string","description":"Custom key for grouping concurrent executions"},"is_trigger":{"type":"boolean","description":"If true, this script is a trigger that can start the flow"},"assets":{"type":"array","description":"External resources this script accesses (S3 objects, resources, etc.)","items":{"type":"object","required":["path","kind"],"properties":{"path":{"type":"string","description":"Path to the asset"},"kind":{"type":"string","description":"Type of asset","enum":["s3object","resource","ducklake","datatable","volume"]},"access_type":{"type":"string","nullable":true,"description":"Access level for this asset","enum":["r","w","rw"]},"alt_access_type":{"type":"string","nullable":true,"description":"Alternative access level","enum":["r","w","rw"]}}}}},"required":["type","content","language","input_transforms"]},"PathScript":{"type":"object","description":"Reference to an existing script by path. Use this when calling a previously saved script instead of writing inline code","properties":{"input_transforms":{"type":"object","description":"Map of parameter names to their values (static or JavaScript expressions). These become the script's input arguments","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"path":{"type":"string","description":"Path to the script in the workspace (e.g., 'f/scripts/send_email')"},"hash":{"type":"string","description":"Optional specific version hash of the script to use"},"type":{"type":"string","enum":["script"]},"tag_override":{"type":"string","description":"Override the script's default worker group tag"},"is_trigger":{"type":"boolean","description":"If true, this script is a trigger that can start the flow"}},"required":["type","path","input_transforms"]},"PathFlow":{"type":"object","description":"Reference to an existing flow by path. Use this to call another flow as a subflow","properties":{"input_transforms":{"type":"object","description":"Map of parameter names to their values (static or JavaScript expressions). These become the subflow's input arguments","additionalProperties":{"$ref":"#/components/schemas/InputTransform"}},"path":{"type":"string","description":"Path to the flow in the workspace (e.g., 'f/flows/process_user')"},"type":{"type":"string","enum":["flow"]}},"required":["type","path","input_transforms"]},"ForloopFlow":{"type":"object","description":"Executes nested modules in a loop over an iterator. Inside the loop, use 'flow_input.iter.value' to access the current iteration value, and 'flow_input.iter.index' for the index. Supports parallel execution for better performance on I/O-bound operations","properties":{"modules":{"type":"array","description":"Steps to execute for each iteration. These can reference the iteration value via 'flow_input.iter.value'","items":{"$ref":"#/components/schemas/FlowModule"}},"iterator":{"description":"JavaScript expression that returns an array to iterate over. Can reference 'results.step_id' or 'flow_input'","$ref":"#/components/schemas/InputTransform"},"skip_failures":{"type":"boolean","description":"If true, iteration failures don't stop the loop. Failed iterations return null"},"type":{"type":"string","enum":["forloopflow"]},"parallel":{"type":"boolean","description":"If true, iterations run concurrently (faster for I/O-bound operations). Use with parallelism to control concurrency"},"parallelism":{"description":"Maximum number of concurrent iterations when parallel=true. Limits resource usage. Can be static number or expression","$ref":"#/components/schemas/InputTransform"},"squash":{"type":"boolean"}},"required":["modules","iterator","skip_failures","type"]},"WhileloopFlow":{"type":"object","description":"Executes nested modules repeatedly while a condition is true. The loop checks the condition after each iteration. Use stop_after_if on modules to control loop termination","properties":{"modules":{"type":"array","description":"Steps to execute in each iteration. Use stop_after_if to control when the loop ends","items":{"$ref":"#/components/schemas/FlowModule"}},"skip_failures":{"type":"boolean","description":"If true, iteration failures don't stop the loop. Failed iterations return null"},"type":{"type":"string","enum":["whileloopflow"]},"parallel":{"type":"boolean","description":"If true, iterations run concurrently (use with caution in while loops)"},"parallelism":{"description":"Maximum number of concurrent iterations when parallel=true","$ref":"#/components/schemas/InputTransform"},"squash":{"type":"boolean"}},"required":["modules","skip_failures","type"]},"BranchOne":{"type":"object","description":"Conditional branching where only the first matching branch executes. Branches are evaluated in order, and the first one with a true expression runs. If no branches match, the default branch executes","properties":{"branches":{"type":"array","description":"Array of branches to evaluate in order. The first branch with expr evaluating to true executes","items":{"type":"object","properties":{"summary":{"type":"string","description":"Short description of this branch condition"},"expr":{"type":"string","description":"JavaScript expression that returns boolean. Can use 'results.step_id' or 'flow_input'. First true expr wins"},"modules":{"type":"array","description":"Steps to execute if this branch's expr is true","items":{"$ref":"#/components/schemas/FlowModule"}}},"required":["modules","expr"]}},"default":{"type":"array","description":"Steps to execute if no branch expressions match","items":{"$ref":"#/components/schemas/FlowModule"}},"type":{"type":"string","enum":["branchone"]}},"required":["branches","default","type"]},"BranchAll":{"type":"object","description":"Parallel branching where all branches execute simultaneously. Unlike BranchOne, all branches run regardless of conditions. Useful for executing independent tasks concurrently","properties":{"branches":{"type":"array","description":"Array of branches that all execute (either in parallel or sequentially)","items":{"type":"object","properties":{"summary":{"type":"string","description":"Short description of this branch's purpose"},"skip_failure":{"type":"boolean","description":"If true, failure in this branch doesn't fail the entire flow"},"modules":{"type":"array","description":"Steps to execute in this branch","items":{"$ref":"#/components/schemas/FlowModule"}}},"required":["modules"]}},"type":{"type":"string","enum":["branchall"]},"parallel":{"type":"boolean","description":"If true, all branches execute concurrently. If false, they execute sequentially"}},"required":["branches","type"]},"AgentTool":{"type":"object","description":"A tool available to an AI agent. Can be a flow module or an external MCP (Model Context Protocol) tool","properties":{"id":{"type":"string","description":"Unique identifier for this tool. Cannot contain spaces - use underscores instead (e.g., 'get_user_data' not 'get user data')"},"summary":{"type":"string","description":"Short description of what this tool does (shown to the AI)"},"value":{"$ref":"#/components/schemas/ToolValue"}},"required":["id","value"]},"ToolValue":{"description":"The implementation of a tool. Can be a flow module (script/flow) or an MCP tool reference","oneOf":[{"$ref":"#/components/schemas/FlowModuleTool"},{"$ref":"#/components/schemas/McpToolValue"},{"$ref":"#/components/schemas/WebsearchToolValue"}],"discriminator":{"propertyName":"tool_type","mapping":{"flowmodule":"#/components/schemas/FlowModuleTool","mcp":"#/components/schemas/McpToolValue","websearch":"#/components/schemas/WebsearchToolValue"}}},"FlowModuleTool":{"description":"A tool implemented as a flow module (script, flow, etc.). The AI can call this like any other flow module","allOf":[{"type":"object","properties":{"tool_type":{"type":"string","enum":["flowmodule"]}},"required":["tool_type"]},{"$ref":"#/components/schemas/FlowModuleValue"}]},"WebsearchToolValue":{"type":"object","description":"A tool implemented as a websearch tool. The AI can call this like any other websearch tool","properties":{"tool_type":{"type":"string","enum":["websearch"]}},"required":["tool_type"]},"McpToolValue":{"type":"object","description":"Reference to an external MCP (Model Context Protocol) tool. The AI can call tools from MCP servers","properties":{"tool_type":{"type":"string","enum":["mcp"]},"resource_path":{"type":"string","description":"Path to the MCP resource/server configuration"},"include_tools":{"type":"array","description":"Whitelist of specific tools to include from this MCP server","items":{"type":"string"}},"exclude_tools":{"type":"array","description":"Blacklist of tools to exclude from this MCP server","items":{"type":"string"}}},"required":["tool_type","resource_path"]},"AiAgent":{"type":"object","description":"AI agent step that can use tools to accomplish tasks. The agent receives inputs and can call any of its configured tools to complete the task","properties":{"input_transforms":{"type":"object","description":"Input parameters for the AI agent mapped to their values","properties":{"provider":{"$ref":"#/components/schemas/ProviderTransform"},"output_type":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Output format type.\\nValid values: 'text' (default) - plain text response, 'image' - image generation\\n"},"user_message":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"The user's prompt/message to the AI agent. Supports variable interpolation with flow.input syntax."},"system_prompt":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"System instructions that guide the AI's behavior, persona, and response style. Optional."},"streaming":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Boolean. If true, stream the AI response incrementally.\\nStreaming events include: token_delta, tool_call, tool_call_arguments, tool_execution, tool_result\\n"},"memory":{"$ref":"#/components/schemas/MemoryTransform"},"output_schema":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"JSON Schema object defining structured output format. Used when you need the AI to return data in a specific shape.\\nSupports standard JSON Schema properties: type, properties, required, items, enum, pattern, minLength, maxLength, minimum, maximum, etc.\\nExample: { type: 'object', properties: { name: { type: 'string' }, age: { type: 'integer' } }, required: ['name'] }\\n"},"user_attachments":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Array of file references (images or PDFs) for the AI agent.\\nFormat: Array<{ bucket: string, key: string }> - S3 object references\\nExample: [{ bucket: 'my-bucket', key: 'documents/report.pdf' }]\\n"},"max_completion_tokens":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Integer. Maximum number of tokens the AI will generate in its response.\\nRange: 1 to 4,294,967,295. Typical values: 256-4096 for most use cases.\\n"},"temperature":{"allOf":[{"$ref":"#/components/schemas/InputTransform"}],"description":"Float. Controls randomness/creativity of responses.\\nRange: 0.0 to 2.0 (provider-dependent)\\n- 0.0 = deterministic, focused responses\\n- 0.7 = balanced (common default)\\n- 1.0+ = more creative/random\\n"}},"required":["provider","user_message","output_type"]},"tools":{"type":"array","description":"Array of tools the agent can use. The agent decides which tools to call based on the task","items":{"$ref":"#/components/schemas/AgentTool"}},"type":{"type":"string","enum":["aiagent"]},"omit_output_from_conversation":{"type":"boolean","default":false,"description":"If true, this AI agent step does not persist its assistant or tool messages to the flow conversation when chat mode is enabled."},"parallel":{"type":"boolean","description":"If true, the agent can execute multiple tool calls in parallel"}},"required":["tools","type","input_transforms"]},"Identity":{"type":"object","description":"Pass-through module that returns its input unchanged. Useful for flow structure or as a placeholder","properties":{"type":{"type":"string","enum":["identity"]},"flow":{"type":"boolean","description":"If true, marks this as a flow identity (special handling)"}},"required":["type"]},"FlowStatus":{"type":"object","properties":{"step":{"type":"integer"},"modules":{"type":"array","items":{"$ref":"#/components/schemas/FlowStatusModule"}},"user_states":{"additionalProperties":true},"preprocessor_module":{"allOf":[{"$ref":"#/components/schemas/FlowStatusModule"}]},"failure_module":{"allOf":[{"$ref":"#/components/schemas/FlowStatusModule"},{"type":"object","properties":{"parent_module":{"type":"string"}}}]},"retry":{"type":"object","properties":{"fail_count":{"type":"integer"},"failed_jobs":{"type":"array","items":{"type":"string","format":"uuid"}}}}},"required":["step","modules","failure_module"]},"FlowStatusModule":{"type":"object","properties":{"type":{"type":"string","enum":["WaitingForPriorSteps","WaitingForEvents","WaitingForExecutor","InProgress","Success","Failure"]},"id":{"type":"string"},"job":{"type":"string","format":"uuid"},"count":{"type":"integer"},"progress":{"type":"integer"},"iterator":{"type":"object","properties":{"index":{"type":"integer"},"itered":{"type":"array","items":{}},"itered_len":{"type":"integer"},"args":{}}},"flow_jobs":{"type":"array","items":{"type":"string"}},"flow_jobs_success":{"type":"array","items":{"type":"boolean"}},"flow_jobs_duration":{"type":"object","properties":{"started_at":{"type":"array","items":{"type":"string"}},"duration_ms":{"type":"array","items":{"type":"integer"}}}},"branch_chosen":{"type":"object","properties":{"type":{"type":"string","enum":["branch","default"]},"branch":{"type":"integer"}},"required":["type"]},"branchall":{"type":"object","properties":{"branch":{"type":"integer"},"len":{"type":"integer"}},"required":["branch","len"]},"approvers":{"type":"array","items":{"type":"object","properties":{"resume_id":{"type":"integer"},"approver":{"type":"string"}},"required":["resume_id","approver"]}},"failed_retries":{"type":"array","items":{"type":"string","format":"uuid"}},"skipped":{"type":"boolean"},"agent_actions":{"type":"array","items":{"type":"object","oneOf":[{"type":"object","properties":{"job_id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"type":{"type":"string","enum":["tool_call"]},"module_id":{"type":"string"}},"required":["job_id","function_name","type","module_id"]},{"type":"object","properties":{"call_id":{"type":"string","format":"uuid"},"function_name":{"type":"string"},"resource_path":{"type":"string"},"type":{"type":"string","enum":["mcp_tool_call"]},"arguments":{"type":"object"}},"required":["call_id","function_name","resource_path","type"]},{"type":"object","properties":{"type":{"type":"string","enum":["web_search"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["message"]}},"required":["content","type"]}]}},"agent_actions_success":{"type":"array","items":{"type":"boolean"}}},"required":["type"]}}`;
|
|
1751
2137
|
export const CLI_COMMANDS = `# Windmill CLI Commands
|
|
1752
2138
|
|
|
1753
2139
|
The Windmill CLI (\`wmill\`) provides commands for managing scripts, flows, apps, and other resources.
|
|
@@ -1785,6 +2171,13 @@ app related commands
|
|
|
1785
2171
|
- \`app lint [app_folder:string]\` - Lint a raw app folder to validate structure and buildability
|
|
1786
2172
|
- \`--fix\` - Attempt to fix common issues (not implemented yet)
|
|
1787
2173
|
- \`app new\` - create a new raw app from a template
|
|
2174
|
+
- \`--summary <summary:string>\` - App summary (short description). Skips the prompt when provided. Triggers non-interactive mode.
|
|
2175
|
+
- \`--path <path:string>\` - App path (e.g., f/folder/my_app or u/username/my_app). Skips the prompt when provided. Triggers non-interactive mode.
|
|
2176
|
+
- \`--framework <framework:string>\` - Framework template: react19 | react18 | svelte5 | vue. Skips the prompt when provided. Triggers non-interactive mode.
|
|
2177
|
+
- \`--datatable <datatable:string>\` - Datatable to wire up. Without this flag in non-interactive mode, no datatable is configured.
|
|
2178
|
+
- \`--schema <schema:string>\` - Schema to use with --datatable. Created (CREATE SCHEMA IF NOT EXISTS) if it doesn't already exist.
|
|
2179
|
+
- \`--overwrite\` - Overwrite the target directory if it already exists, without prompting.
|
|
2180
|
+
- \`--no-open-in-desktop\` - Do not prompt to open the new app in Claude Desktop.
|
|
1788
2181
|
- \`app generate-agents [app_folder:string]\` - regenerate AGENTS.md and DATATABLES.md from remote workspace
|
|
1789
2182
|
- \`app set-permissioned-as <path:string> <email:string>\` - Set the on_behalf_of_email for an app (requires admin or wm_deployers group)
|
|
1790
2183
|
|
|
@@ -1821,10 +2214,13 @@ workspace dependencies related commands
|
|
|
1821
2214
|
|
|
1822
2215
|
### dev
|
|
1823
2216
|
|
|
1824
|
-
|
|
2217
|
+
Watch local file changes and live-reload the dev page for preview. Does NOT deploy to the remote workspace — use wmill sync push for that.
|
|
1825
2218
|
|
|
1826
2219
|
**Options:**
|
|
1827
|
-
- \`--includes <pattern...:string>\` - Filter paths
|
|
2220
|
+
- \`--includes <pattern...:string>\` - Filter paths given a glob pattern or path
|
|
2221
|
+
- \`--proxy-port <port:number>\` - Port for a localhost reverse proxy to the remote Windmill server
|
|
2222
|
+
- \`--path <path:string>\` - Watch a specific windmill path (e.g., u/admin/my_script or f/my_flow)
|
|
2223
|
+
- \`--no-open\` - Do not open the browser automatically
|
|
1828
2224
|
|
|
1829
2225
|
### docs
|
|
1830
2226
|
|
|
@@ -1911,6 +2307,15 @@ Generate metadata (locks, schemas) for all scripts, flows, and apps
|
|
|
1911
2307
|
- \`-i --includes <patterns:file[]>\` - Comma separated patterns to specify which files to include
|
|
1912
2308
|
- \`-e --excludes <patterns:file[]>\` - Comma separated patterns to specify which files to exclude
|
|
1913
2309
|
|
|
2310
|
+
**Subcommands:**
|
|
2311
|
+
|
|
2312
|
+
- \`generate-metadata rehash [folder:string]\`
|
|
2313
|
+
- \`--skip-scripts\` - Skip processing scripts
|
|
2314
|
+
- \`--skip-flows\` - Skip processing flows
|
|
2315
|
+
- \`--skip-apps\` - Skip processing apps
|
|
2316
|
+
- \`-i --includes <patterns:file[]>\` - Comma separated patterns to specify which files to include
|
|
2317
|
+
- \`-e --excludes <patterns:file[]>\` - Comma separated patterns to specify which files to exclude
|
|
2318
|
+
|
|
1914
2319
|
### gitsync-settings
|
|
1915
2320
|
|
|
1916
2321
|
Manage git-sync settings between local wmill.yaml and Windmill backend
|
|
@@ -2011,6 +2416,11 @@ sync local with a remote instance or the opposite (push or pull)
|
|
|
2011
2416
|
- \`-o, --output-file <file:string>\` - Write YAML to a file instead of stdout
|
|
2012
2417
|
- \`--show-secrets\` - Include sensitive fields (license key, JWT secret) without prompting
|
|
2013
2418
|
- \`--instance <instance:string>\` - Name of the instance, override the active instance
|
|
2419
|
+
- \`instance connect-slack\`
|
|
2420
|
+
- \`--bot-token <bot_token:string>\` - Slack bot token (xoxb-...)
|
|
2421
|
+
- \`--team-id <team_id:string>\` - Slack team id
|
|
2422
|
+
- \`--team-name <team_name:string>\` - Slack team name
|
|
2423
|
+
- \`--instance <instance:string>\` - Instance profile to connect against (defaults to the active instance)
|
|
2014
2424
|
|
|
2015
2425
|
### job
|
|
2016
2426
|
|
|
@@ -2114,6 +2524,7 @@ schedule related commands
|
|
|
2114
2524
|
- \`schedule new <path:string>\` - create a new schedule locally
|
|
2115
2525
|
- \`schedule push <file_path:string> <remote_path:string>\` - push a local schedule spec. This overrides any remote versions.
|
|
2116
2526
|
- \`schedule enable <path:string>\` - Enable a schedule
|
|
2527
|
+
- \`--force\` - Bypass the fork-conflict warning when the parent workspace has the same schedule (acknowledges that both crons will fire)
|
|
2117
2528
|
- \`schedule disable <path:string>\` - Disable a schedule
|
|
2118
2529
|
- \`schedule set-permissioned-as <path:string> <email:string>\` - Set the email (run-as user) for a schedule (requires admin or wm_deployers group)
|
|
2119
2530
|
|
|
@@ -2252,12 +2663,12 @@ trigger related commands
|
|
|
2252
2663
|
- \`--json\` - Output as JSON (for piping to jq)
|
|
2253
2664
|
- \`trigger get <path:string>\` - get a trigger's details
|
|
2254
2665
|
- \`--json\` - Output as JSON (for piping to jq)
|
|
2255
|
-
- \`--kind <kind:string>\` - Trigger kind (http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email). Recommended for faster lookup
|
|
2666
|
+
- \`--kind <kind:string>\` - Trigger kind (http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, azure, email). Recommended for faster lookup
|
|
2256
2667
|
- \`trigger new <path:string>\` - create a new trigger locally
|
|
2257
|
-
- \`--kind <kind:string>\` - Trigger kind (required: http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email)
|
|
2668
|
+
- \`--kind <kind:string>\` - Trigger kind (required: http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, azure, email)
|
|
2258
2669
|
- \`trigger push <file_path:string> <remote_path:string>\` - push a local trigger spec. This overrides any remote versions.
|
|
2259
2670
|
- \`trigger set-permissioned-as <path:string> <email:string>\` - Set the email (run-as user) for a trigger (requires admin or wm_deployers group)
|
|
2260
|
-
- \`--kind <kind:string>\` - Trigger kind (required: http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, email)
|
|
2671
|
+
- \`--kind <kind:string>\` - Trigger kind (required: http, websocket, kafka, nats, postgres, mqtt, sqs, gcp, azure, email)
|
|
2261
2672
|
|
|
2262
2673
|
### user
|
|
2263
2674
|
|
|
@@ -2359,6 +2770,11 @@ workspace related commands
|
|
|
2359
2770
|
- \`--exclude <items:string>\` - Comma-separated kind:path items to exclude
|
|
2360
2771
|
- \`--preserve-on-behalf-of\` - Preserve original on_behalf_of/permissioned_as values
|
|
2361
2772
|
- \`-y --yes\` - Non-interactive mode (deploy without prompts)
|
|
2773
|
+
- \`workspace connect-slack\` - Non-interactively connect Slack to the active workspace using a pre-minted bot token (xoxb-...). Produces the same artifacts as the UI OAuth flow: workspace_settings fields, g/slack group, f/slack_bot folder, and the encrypted bot token variable + resource at f/slack_bot/bot_token.
|
|
2774
|
+
- \`--bot-token <bot_token:string>\` - Slack bot token (xoxb-...)
|
|
2775
|
+
- \`--team-id <team_id:string>\` - Slack team id
|
|
2776
|
+
- \`--team-name <team_name:string>\` - Slack team name
|
|
2777
|
+
- \`workspace disconnect-slack\`
|
|
2362
2778
|
|
|
2363
2779
|
`;
|
|
2364
2780
|
export const LANG_BASH = `# Bash
|
|
@@ -2422,6 +2838,37 @@ Name the parameters by adding comments before the statement:
|
|
|
2422
2838
|
-- @name2 (int64) = 0
|
|
2423
2839
|
SELECT * FROM users WHERE name = @name1 AND age > @name2;
|
|
2424
2840
|
\`\`\`
|
|
2841
|
+
|
|
2842
|
+
## Receiving an S3Object as a script parameter
|
|
2843
|
+
|
|
2844
|
+
Declare the arg with type \`(s3object)\`. Windmill renders an S3 file picker for
|
|
2845
|
+
it, downloads the file, and binds it as a \`STRING\` JSON parameter — Parquet/CSV
|
|
2846
|
+
files are decoded server-side into a JSON array of records, JSON/JSONL pass
|
|
2847
|
+
through. Consume with \`JSON_EXTRACT_ARRAY\` / \`JSON_VALUE\`:
|
|
2848
|
+
|
|
2849
|
+
\`\`\`sql
|
|
2850
|
+
-- @file (s3object)
|
|
2851
|
+
SELECT
|
|
2852
|
+
CAST(JSON_VALUE(row, '$.id') AS INT64) AS id,
|
|
2853
|
+
JSON_VALUE(row, '$.name') AS name
|
|
2854
|
+
FROM UNNEST(JSON_EXTRACT_ARRAY(@file)) AS row;
|
|
2855
|
+
\`\`\`
|
|
2856
|
+
|
|
2857
|
+
## Streaming query results to S3
|
|
2858
|
+
|
|
2859
|
+
Add a \`-- s3\` directive at the top of the script to stream the result set to S3
|
|
2860
|
+
instead of returning rows. Windmill writes the file and returns its \`S3Object\`
|
|
2861
|
+
as the script result.
|
|
2862
|
+
|
|
2863
|
+
\`\`\`sql
|
|
2864
|
+
-- s3 prefix=exports/users format=parquet
|
|
2865
|
+
SELECT id, name FROM users;
|
|
2866
|
+
\`\`\`
|
|
2867
|
+
|
|
2868
|
+
All keys are optional: \`prefix\` (object key prefix), \`storage\` (named storage —
|
|
2869
|
+
omit to use the workspace default), \`format\` (\`json\` (default), \`parquet\`, or
|
|
2870
|
+
\`csv\`). Use this for large result sets — rows stream directly to S3 instead of
|
|
2871
|
+
being buffered, bypassing the 10000-row return cap.
|
|
2425
2872
|
`;
|
|
2426
2873
|
export const LANG_BUN = `# TypeScript (Bun)
|
|
2427
2874
|
|
|
@@ -2505,19 +2952,20 @@ export async function preprocessor(event: Event) {
|
|
|
2505
2952
|
|
|
2506
2953
|
## S3 Object Operations
|
|
2507
2954
|
|
|
2508
|
-
Windmill provides built-in support for S3-compatible storage operations.
|
|
2955
|
+
Windmill provides built-in support for S3-compatible storage operations. The \`wmill.S3Object\` type covers both the \`s3://storage/key\` URI form (\`s3:///key\` for the workspace default storage) and the \`{ s3, storage? }\` record form — always use it instead of redefining your own.
|
|
2509
2956
|
|
|
2510
|
-
### S3Object
|
|
2511
|
-
|
|
2512
|
-
The S3Object type represents a file in S3 storage:
|
|
2957
|
+
### Receiving an S3Object as a script parameter
|
|
2513
2958
|
|
|
2514
2959
|
\`\`\`typescript
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2960
|
+
import * as wmill from "windmill-client";
|
|
2961
|
+
|
|
2962
|
+
export async function main(file: wmill.S3Object) {
|
|
2963
|
+
const content = await wmill.loadS3File(file);
|
|
2964
|
+
// ...
|
|
2965
|
+
}
|
|
2518
2966
|
\`\`\`
|
|
2519
2967
|
|
|
2520
|
-
|
|
2968
|
+
### S3 operations
|
|
2521
2969
|
|
|
2522
2970
|
\`\`\`typescript
|
|
2523
2971
|
import * as wmill from "windmill-client";
|
|
@@ -2529,7 +2977,7 @@ const content: Uint8Array = await wmill.loadS3File(s3object);
|
|
|
2529
2977
|
const blob: Blob = await wmill.loadS3FileStream(s3object);
|
|
2530
2978
|
|
|
2531
2979
|
// Write file to S3
|
|
2532
|
-
const result: S3Object = await wmill.writeS3File(
|
|
2980
|
+
const result: wmill.S3Object = await wmill.writeS3File(
|
|
2533
2981
|
s3object, // Target path (or undefined to auto-generate)
|
|
2534
2982
|
fileContent, // string or Blob
|
|
2535
2983
|
s3ResourcePath // Optional: specific S3 resource to use
|
|
@@ -2616,19 +3064,20 @@ export async function preprocessor(event: Event) {
|
|
|
2616
3064
|
|
|
2617
3065
|
## S3 Object Operations
|
|
2618
3066
|
|
|
2619
|
-
Windmill provides built-in support for S3-compatible storage operations.
|
|
2620
|
-
|
|
2621
|
-
### S3Object Type
|
|
3067
|
+
Windmill provides built-in support for S3-compatible storage operations. The \`wmill.S3Object\` type covers both the \`s3://storage/key\` URI form (\`s3:///key\` for the workspace default storage) and the \`{ s3, storage? }\` record form — always use it instead of redefining your own.
|
|
2622
3068
|
|
|
2623
|
-
|
|
3069
|
+
### Receiving an S3Object as a script parameter
|
|
2624
3070
|
|
|
2625
3071
|
\`\`\`typescript
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
3072
|
+
import * as wmill from "windmill-client";
|
|
3073
|
+
|
|
3074
|
+
export async function main(file: wmill.S3Object) {
|
|
3075
|
+
const content = await wmill.loadS3File(file);
|
|
3076
|
+
// ...
|
|
3077
|
+
}
|
|
2629
3078
|
\`\`\`
|
|
2630
3079
|
|
|
2631
|
-
|
|
3080
|
+
### S3 operations
|
|
2632
3081
|
|
|
2633
3082
|
\`\`\`typescript
|
|
2634
3083
|
import * as wmill from "windmill-client";
|
|
@@ -2640,7 +3089,7 @@ const content: Uint8Array = await wmill.loadS3File(s3object);
|
|
|
2640
3089
|
const blob: Blob = await wmill.loadS3FileStream(s3object);
|
|
2641
3090
|
|
|
2642
3091
|
// Write file to S3
|
|
2643
|
-
const result: S3Object = await wmill.writeS3File(
|
|
3092
|
+
const result: wmill.S3Object = await wmill.writeS3File(
|
|
2644
3093
|
s3object, // Target path (or undefined to auto-generate)
|
|
2645
3094
|
fileContent, // string or Blob
|
|
2646
3095
|
s3ResourcePath // Optional: specific S3 resource to use
|
|
@@ -2775,19 +3224,20 @@ export async function preprocessor(event: Event) {
|
|
|
2775
3224
|
|
|
2776
3225
|
## S3 Object Operations
|
|
2777
3226
|
|
|
2778
|
-
Windmill provides built-in support for S3-compatible storage operations.
|
|
2779
|
-
|
|
2780
|
-
### S3Object Type
|
|
3227
|
+
Windmill provides built-in support for S3-compatible storage operations. The \`wmill.S3Object\` type covers both the \`s3://storage/key\` URI form (\`s3:///key\` for the workspace default storage) and the \`{ s3, storage? }\` record form — always use it instead of redefining your own.
|
|
2781
3228
|
|
|
2782
|
-
|
|
3229
|
+
### Receiving an S3Object as a script parameter
|
|
2783
3230
|
|
|
2784
3231
|
\`\`\`typescript
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
3232
|
+
import * as wmill from "windmill-client";
|
|
3233
|
+
|
|
3234
|
+
export async function main(file: wmill.S3Object) {
|
|
3235
|
+
const content = await wmill.loadS3File(file);
|
|
3236
|
+
// ...
|
|
3237
|
+
}
|
|
2788
3238
|
\`\`\`
|
|
2789
3239
|
|
|
2790
|
-
|
|
3240
|
+
### S3 operations
|
|
2791
3241
|
|
|
2792
3242
|
\`\`\`typescript
|
|
2793
3243
|
import * as wmill from "windmill-client";
|
|
@@ -2799,7 +3249,7 @@ const content: Uint8Array = await wmill.loadS3File(s3object);
|
|
|
2799
3249
|
const blob: Blob = await wmill.loadS3FileStream(s3object);
|
|
2800
3250
|
|
|
2801
3251
|
// Write file to S3
|
|
2802
|
-
const result: S3Object = await wmill.writeS3File(
|
|
3252
|
+
const result: wmill.S3Object = await wmill.writeS3File(
|
|
2803
3253
|
s3object, // Target path (or undefined to auto-generate)
|
|
2804
3254
|
fileContent, // string or Blob
|
|
2805
3255
|
s3ResourcePath // Optional: specific S3 resource to use
|
|
@@ -2857,6 +3307,30 @@ SELECT * FROM read_parquet('s3:///path/to/file.parquet');
|
|
|
2857
3307
|
-- JSON files
|
|
2858
3308
|
SELECT * FROM read_json('s3:///path/to/file.json');
|
|
2859
3309
|
\`\`\`
|
|
3310
|
+
|
|
3311
|
+
### Receiving an S3Object as a script parameter
|
|
3312
|
+
|
|
3313
|
+
Declare the arg with type \`(s3object)\`. Windmill renders an S3 file picker for it
|
|
3314
|
+
and binds the arg as the bare \`s3://storage/key\` URI, which DuckDB's reader
|
|
3315
|
+
functions consume directly:
|
|
3316
|
+
|
|
3317
|
+
\`\`\`sql
|
|
3318
|
+
-- $file (s3object)
|
|
3319
|
+
SELECT * FROM read_parquet($file);
|
|
3320
|
+
\`\`\`
|
|
3321
|
+
|
|
3322
|
+
Works with any DuckDB reader: \`read_csv($file)\`, \`read_json($file)\`, etc.
|
|
3323
|
+
|
|
3324
|
+
### Writing query results to S3
|
|
3325
|
+
|
|
3326
|
+
DuckDB writes to S3 natively via \`COPY ... TO\`:
|
|
3327
|
+
|
|
3328
|
+
\`\`\`sql
|
|
3329
|
+
COPY (SELECT * FROM users) TO 's3:///exports/users.parquet' (FORMAT PARQUET);
|
|
3330
|
+
\`\`\`
|
|
3331
|
+
|
|
3332
|
+
Use this instead of the \`-- s3\` streaming directive supported by the other SQL
|
|
3333
|
+
dialects — that directive is not available in DuckDB.
|
|
2860
3334
|
`;
|
|
2861
3335
|
export const LANG_GO = `# Go
|
|
2862
3336
|
|
|
@@ -3013,6 +3487,36 @@ Name the parameters by adding comments before the statement:
|
|
|
3013
3487
|
-- @P2 name2 (int) = 0
|
|
3014
3488
|
SELECT * FROM users WHERE name = @P1 AND age > @P2;
|
|
3015
3489
|
\`\`\`
|
|
3490
|
+
|
|
3491
|
+
## Receiving an S3Object as a script parameter
|
|
3492
|
+
|
|
3493
|
+
Declare the arg with type \`(s3object)\`. Windmill renders an S3 file picker for
|
|
3494
|
+
it, downloads the file, and binds it as \`nvarchar(max)\` JSON text — Parquet/CSV
|
|
3495
|
+
files are decoded server-side into a JSON array of records, JSON/JSONL pass
|
|
3496
|
+
through. Consume with \`OPENJSON\`:
|
|
3497
|
+
|
|
3498
|
+
\`\`\`sql
|
|
3499
|
+
-- @P1 file (s3object)
|
|
3500
|
+
SELECT id, name
|
|
3501
|
+
FROM OPENJSON(@P1)
|
|
3502
|
+
WITH (id INT, name NVARCHAR(200));
|
|
3503
|
+
\`\`\`
|
|
3504
|
+
|
|
3505
|
+
## Streaming query results to S3
|
|
3506
|
+
|
|
3507
|
+
Add a \`-- s3\` directive at the top of the script to stream the result set to S3
|
|
3508
|
+
instead of returning rows. Windmill writes the file and returns its \`S3Object\`
|
|
3509
|
+
as the script result.
|
|
3510
|
+
|
|
3511
|
+
\`\`\`sql
|
|
3512
|
+
-- s3 prefix=exports/users format=parquet
|
|
3513
|
+
SELECT id, name FROM users;
|
|
3514
|
+
\`\`\`
|
|
3515
|
+
|
|
3516
|
+
All keys are optional: \`prefix\` (object key prefix), \`storage\` (named storage —
|
|
3517
|
+
omit to use the workspace default), \`format\` (\`json\` (default), \`parquet\`, or
|
|
3518
|
+
\`csv\`). Use this for large result sets — rows stream directly to S3 instead of
|
|
3519
|
+
being buffered as the script return value.
|
|
3016
3520
|
`;
|
|
3017
3521
|
export const LANG_MYSQL = `# MySQL
|
|
3018
3522
|
|
|
@@ -3025,6 +3529,37 @@ Name the parameters by adding comments before the statement:
|
|
|
3025
3529
|
-- ? name2 (int) = 0
|
|
3026
3530
|
SELECT * FROM users WHERE name = ? AND age > ?;
|
|
3027
3531
|
\`\`\`
|
|
3532
|
+
|
|
3533
|
+
## Receiving an S3Object as a script parameter
|
|
3534
|
+
|
|
3535
|
+
Declare the arg with type \`(s3object)\`. Windmill renders an S3 file picker for
|
|
3536
|
+
it, downloads the file, and binds it as JSON text — Parquet/CSV files are
|
|
3537
|
+
decoded server-side into a JSON array of records, JSON/JSONL pass through.
|
|
3538
|
+
Consume with \`JSON_TABLE\`:
|
|
3539
|
+
|
|
3540
|
+
\`\`\`sql
|
|
3541
|
+
-- ? file (s3object)
|
|
3542
|
+
SELECT id, name
|
|
3543
|
+
FROM JSON_TABLE(?, '$[*]'
|
|
3544
|
+
COLUMNS (id INT PATH '$.id', name VARCHAR(200) PATH '$.name')
|
|
3545
|
+
) AS r;
|
|
3546
|
+
\`\`\`
|
|
3547
|
+
|
|
3548
|
+
## Streaming query results to S3
|
|
3549
|
+
|
|
3550
|
+
Add a \`-- s3\` directive at the top of the script to stream the result set to S3
|
|
3551
|
+
instead of returning rows. Windmill writes the file and returns its \`S3Object\`
|
|
3552
|
+
as the script result.
|
|
3553
|
+
|
|
3554
|
+
\`\`\`sql
|
|
3555
|
+
-- s3 prefix=exports/users format=parquet
|
|
3556
|
+
SELECT id, name FROM users;
|
|
3557
|
+
\`\`\`
|
|
3558
|
+
|
|
3559
|
+
All keys are optional: \`prefix\` (object key prefix), \`storage\` (named storage —
|
|
3560
|
+
omit to use the workspace default), \`format\` (\`json\` (default), \`parquet\`, or
|
|
3561
|
+
\`csv\`). Use this for large result sets — rows stream directly to S3 instead of
|
|
3562
|
+
being buffered as the script return value.
|
|
3028
3563
|
`;
|
|
3029
3564
|
export const LANG_NATIVETS = `# TypeScript (Native)
|
|
3030
3565
|
|
|
@@ -3173,6 +3708,35 @@ Name the parameters by adding comments at the beginning of the script (without s
|
|
|
3173
3708
|
-- $2 name2 = default_value
|
|
3174
3709
|
SELECT * FROM users WHERE name = $1::TEXT AND age > $2::INT;
|
|
3175
3710
|
\`\`\`
|
|
3711
|
+
|
|
3712
|
+
## Receiving an S3Object as a script parameter
|
|
3713
|
+
|
|
3714
|
+
Declare the arg with type \`(s3object)\`. Windmill renders an S3 file picker for
|
|
3715
|
+
it, downloads the file, and binds it as a \`jsonb\` parameter — Parquet/CSV files
|
|
3716
|
+
are decoded server-side into a JSON array of records, JSON/JSONL pass through.
|
|
3717
|
+
Consume with \`jsonb_to_recordset\` (or any \`jsonb\` API):
|
|
3718
|
+
|
|
3719
|
+
\`\`\`sql
|
|
3720
|
+
-- $1 file (s3object)
|
|
3721
|
+
SELECT *
|
|
3722
|
+
FROM jsonb_to_recordset($1::jsonb) AS r(id INT, name TEXT);
|
|
3723
|
+
\`\`\`
|
|
3724
|
+
|
|
3725
|
+
## Streaming query results to S3
|
|
3726
|
+
|
|
3727
|
+
Add a \`-- s3\` directive at the top of the script to stream the result set to S3
|
|
3728
|
+
instead of returning rows. Windmill writes the file and returns its \`S3Object\`
|
|
3729
|
+
as the script result.
|
|
3730
|
+
|
|
3731
|
+
\`\`\`sql
|
|
3732
|
+
-- s3 prefix=exports/users format=parquet
|
|
3733
|
+
SELECT id, name FROM users;
|
|
3734
|
+
\`\`\`
|
|
3735
|
+
|
|
3736
|
+
All keys are optional: \`prefix\` (object key prefix), \`storage\` (named storage —
|
|
3737
|
+
omit to use the workspace default), \`format\` (\`json\` (default), \`parquet\`, or
|
|
3738
|
+
\`csv\`). Use this for large result sets — rows stream directly to S3 instead of
|
|
3739
|
+
being buffered as the script return value.
|
|
3176
3740
|
`;
|
|
3177
3741
|
export const LANG_POWERSHELL = `# PowerShell
|
|
3178
3742
|
|
|
@@ -3330,6 +3894,21 @@ def preprocessor(event: Event):
|
|
|
3330
3894
|
|
|
3331
3895
|
Windmill provides built-in support for S3-compatible storage operations.
|
|
3332
3896
|
|
|
3897
|
+
### Receiving an S3Object as a script parameter
|
|
3898
|
+
|
|
3899
|
+
To accept a file from S3 as input to a script, type the parameter with \`S3Object\` (imported from \`wmill\`):
|
|
3900
|
+
|
|
3901
|
+
\`\`\`python
|
|
3902
|
+
import wmill
|
|
3903
|
+
from wmill import S3Object
|
|
3904
|
+
|
|
3905
|
+
def main(file: S3Object):
|
|
3906
|
+
content = wmill.load_s3_file(file)
|
|
3907
|
+
# ...
|
|
3908
|
+
\`\`\`
|
|
3909
|
+
|
|
3910
|
+
### S3 operations
|
|
3911
|
+
|
|
3333
3912
|
\`\`\`python
|
|
3334
3913
|
import wmill
|
|
3335
3914
|
|
|
@@ -3522,4 +4101,35 @@ Name the parameters by adding comments before the statement:
|
|
|
3522
4101
|
-- ? name2 (number) = 0
|
|
3523
4102
|
SELECT * FROM users WHERE name = ? AND age > ?;
|
|
3524
4103
|
\`\`\`
|
|
4104
|
+
|
|
4105
|
+
## Receiving an S3Object as a script parameter
|
|
4106
|
+
|
|
4107
|
+
Declare the arg with type \`(s3object)\`. Windmill renders an S3 file picker for
|
|
4108
|
+
it, downloads the file, and binds it as JSON text — Parquet/CSV files are
|
|
4109
|
+
decoded server-side into a JSON array of records, JSON/JSONL pass through.
|
|
4110
|
+
Wrap the bind with \`PARSE_JSON(?)\` and walk it with \`LATERAL FLATTEN\`:
|
|
4111
|
+
|
|
4112
|
+
\`\`\`sql
|
|
4113
|
+
-- ? file (s3object)
|
|
4114
|
+
SELECT
|
|
4115
|
+
v.value:id::NUMBER AS id,
|
|
4116
|
+
v.value:name::STRING AS name
|
|
4117
|
+
FROM LATERAL FLATTEN(input => PARSE_JSON(?)) v;
|
|
4118
|
+
\`\`\`
|
|
4119
|
+
|
|
4120
|
+
## Streaming query results to S3
|
|
4121
|
+
|
|
4122
|
+
Add a \`-- s3\` directive at the top of the script to stream the result set to S3
|
|
4123
|
+
instead of returning rows. Windmill writes the file and returns its \`S3Object\`
|
|
4124
|
+
as the script result.
|
|
4125
|
+
|
|
4126
|
+
\`\`\`sql
|
|
4127
|
+
-- s3 prefix=exports/users format=parquet
|
|
4128
|
+
SELECT id, name FROM users;
|
|
4129
|
+
\`\`\`
|
|
4130
|
+
|
|
4131
|
+
All keys are optional: \`prefix\` (object key prefix), \`storage\` (named storage —
|
|
4132
|
+
omit to use the workspace default), \`format\` (\`json\` (default), \`parquet\`, or
|
|
4133
|
+
\`csv\`). Use this for large result sets — rows stream directly to S3 instead of
|
|
4134
|
+
being buffered, bypassing the 10000-row return cap.
|
|
3525
4135
|
`;
|