windmill-components 1.531.1 → 1.537.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/package/components/ArgInput.svelte +69 -19
  2. package/package/components/Auth0Setting.svelte +8 -3
  3. package/package/components/Dev.svelte +5 -4
  4. package/package/components/DiffDrawer.svelte +2 -2
  5. package/package/components/DiffEditor.svelte +34 -37
  6. package/package/components/DiffEditor.svelte.d.ts +23 -39
  7. package/package/components/EditableSchemaForm.svelte +67 -67
  8. package/package/components/EditableSchemaForm.svelte.d.ts +3 -3
  9. package/package/components/Editor.svelte +32 -11
  10. package/package/components/Editor.svelte.d.ts +6 -0
  11. package/package/components/EditorBar.svelte +2 -2
  12. package/package/components/EditorBar.svelte.d.ts +1 -0
  13. package/package/components/FieldHeader.svelte +1 -1
  14. package/package/components/FlowBuilder.svelte +7 -4
  15. package/package/components/FlowPreviewContent.svelte +3 -3
  16. package/package/components/FlowStatusViewer.svelte +28 -0
  17. package/package/components/FlowStatusViewerInner.svelte +72 -20
  18. package/package/components/FlowStatusViewerInner.svelte.d.ts +7 -0
  19. package/package/components/ModulePreview.svelte +2 -1
  20. package/package/components/ModulePreview.svelte.d.ts +1 -0
  21. package/package/components/ModulePreviewForm.svelte +72 -65
  22. package/package/components/ModulePreviewResultViewer.svelte +13 -18
  23. package/package/components/ModuleTest.svelte +10 -6
  24. package/package/components/ModuleTest.svelte.d.ts +1 -0
  25. package/package/components/OktaSetting.svelte +8 -3
  26. package/package/components/Portal.svelte +11 -7
  27. package/package/components/Portal.svelte.d.ts +19 -39
  28. package/package/components/ResourceEditor.svelte +4 -0
  29. package/package/components/RunForm.svelte +2 -2
  30. package/package/components/RunForm.svelte.d.ts +1 -1
  31. package/package/components/RunFormAdvancedPopup.svelte +13 -1
  32. package/package/components/SchemaForm.svelte +1 -2
  33. package/package/components/ScriptBuilder.svelte +1 -1
  34. package/package/components/ScriptEditor.svelte +22 -7
  35. package/package/components/SimpleEditor.svelte +0 -1
  36. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  37. package/package/components/apps/components/layout/AppModal.svelte +2 -2
  38. package/package/components/apps/editor/component/ComponentNavigation.svelte +3 -2
  39. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptEditor.svelte +1 -1
  40. package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +0 -1
  41. package/package/components/apps/editor/settingsPanel/ArrayStaticInputEditor.svelte +3 -1
  42. package/package/components/apps/editor/settingsPanel/GridCondition.svelte +3 -1
  43. package/package/components/apps/editor/settingsPanel/GridNavbar.svelte +3 -1
  44. package/package/components/apps/editor/settingsPanel/GridTab.svelte +3 -1
  45. package/package/components/apps/editor/settingsPanel/OneOfInputSpecsEditor.svelte +55 -53
  46. package/package/components/apps/editor/settingsPanel/TableActions.svelte +3 -1
  47. package/package/components/common/button/model.d.ts +1 -1
  48. package/package/components/common/drawer/Disposable.svelte +51 -30
  49. package/package/components/common/drawer/Disposable.svelte.d.ts +12 -44
  50. package/package/components/common/drawer/Drawer.svelte +15 -11
  51. package/package/components/copilot/FlowInlineScriptAIButton.svelte +4 -2
  52. package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +4 -1
  53. package/package/components/copilot/MetadataGen.svelte +14 -3
  54. package/package/components/copilot/autocomplete/Autocompletor.js +0 -2
  55. package/package/components/copilot/chat/AIChat.svelte +2 -4
  56. package/package/components/copilot/chat/AIChatInput.svelte +3 -3
  57. package/package/components/copilot/chat/AIChatManager.svelte.js +24 -12
  58. package/package/components/copilot/chat/AvailableContextList.svelte +243 -26
  59. package/package/components/copilot/chat/AvailableContextList.svelte.d.ts +2 -1
  60. package/package/components/copilot/chat/ContextElementBadge.svelte +31 -15
  61. package/package/components/copilot/chat/ContextElementBadge.svelte.d.ts +5 -20
  62. package/package/components/copilot/chat/ContextManager.svelte.d.ts +15 -2
  63. package/package/components/copilot/chat/ContextManager.svelte.js +134 -24
  64. package/package/components/copilot/chat/ContextTextarea.svelte +22 -49
  65. package/package/components/copilot/chat/ToolContentDisplay.svelte +10 -1
  66. package/package/components/copilot/chat/ToolExecutionDisplay.svelte +3 -3
  67. package/package/components/copilot/chat/context.d.ts +19 -1
  68. package/package/components/copilot/chat/context.js +1 -0
  69. package/package/components/copilot/chat/flow/FlowAIChat.svelte +109 -7
  70. package/package/components/copilot/chat/flow/core.d.ts +13 -1
  71. package/package/components/copilot/chat/flow/core.js +171 -19
  72. package/package/components/copilot/chat/flow/uiIntents.d.ts +8 -0
  73. package/package/components/copilot/chat/flow/uiIntents.js +5 -0
  74. package/package/components/copilot/chat/flow/useUiIntent.d.ts +5 -0
  75. package/package/components/copilot/chat/flow/useUiIntent.js +12 -0
  76. package/package/components/copilot/chat/monaco-adapter.d.ts +22 -4
  77. package/package/components/copilot/chat/monaco-adapter.js +55 -16
  78. package/package/components/copilot/chat/script/core.d.ts +2 -2
  79. package/package/components/copilot/chat/script/core.js +54 -124
  80. package/package/components/copilot/chat/shared.d.ts +14 -2
  81. package/package/components/copilot/chat/shared.js +170 -7
  82. package/package/components/copilot/lib.js +12 -7
  83. package/package/components/copilot/shared.d.ts +1 -1
  84. package/package/components/copilot/shared.js +16 -10
  85. package/package/components/flows/FlowEditor.svelte +15 -1
  86. package/package/components/flows/FlowEditor.svelte.d.ts +1 -0
  87. package/package/components/flows/FlowModuleIcon.svelte +39 -0
  88. package/package/components/flows/FlowModuleIcon.svelte.d.ts +10 -0
  89. package/package/components/flows/common/FlowCardHeader.svelte +4 -1
  90. package/package/components/flows/content/FlowBranchesAllWrapper.svelte +6 -0
  91. package/package/components/flows/content/FlowBranchesOneWrapper.svelte +6 -0
  92. package/package/components/flows/content/FlowEditorPanel.svelte +2 -1
  93. package/package/components/flows/content/FlowEditorPanel.svelte.d.ts +1 -0
  94. package/package/components/flows/content/FlowInput.svelte +31 -34
  95. package/package/components/flows/content/FlowInput.svelte.d.ts +1 -0
  96. package/package/components/flows/content/FlowLoop.svelte +7 -0
  97. package/package/components/flows/content/FlowModuleComponent.svelte +39 -44
  98. package/package/components/flows/content/FlowModuleScript.svelte +1 -1
  99. package/package/components/flows/content/FlowModuleSuspend.svelte +16 -18
  100. package/package/components/flows/content/FlowWhileLoop.svelte +6 -0
  101. package/package/components/flows/content/ScriptEditorDrawer.svelte +9 -11
  102. package/package/components/flows/dfs.d.ts +1 -1
  103. package/package/components/flows/dfs.js +6 -6
  104. package/package/components/flows/flowInfers.js +7 -7
  105. package/package/components/flows/flowStateUtils.svelte.js +1 -2
  106. package/package/components/flows/map/FlowModuleSchemaItem.svelte +12 -26
  107. package/package/components/flows/map/MapItem.svelte +12 -39
  108. package/package/components/flows/map/VirtualItem.svelte +1 -1
  109. package/package/components/flows/pickers/TopLevelNode.svelte +1 -1
  110. package/package/components/flows/propPicker/InputPickerInner.svelte +5 -5
  111. package/package/components/flows/propPicker/OutputPickerInner.svelte +143 -118
  112. package/package/components/flows/propPicker/OutputPickerInner.svelte.d.ts +7 -16
  113. package/package/components/flows/{testSteps.svelte.d.ts → stepsInputArgs.svelte.d.ts} +2 -1
  114. package/package/components/flows/{testSteps.svelte.js → stepsInputArgs.svelte.js} +15 -3
  115. package/package/components/flows/types.d.ts +16 -3
  116. package/package/components/flows/utils.js +3 -0
  117. package/package/components/graph/FlowGraphV2.svelte +1 -1
  118. package/package/components/graph/renderers/nodes/AIToolNode.svelte +4 -4
  119. package/package/components/graph/renderers/nodes/NewAIToolNode.svelte +71 -54
  120. package/package/components/propertyPicker/ObjectViewer.svelte +11 -3
  121. package/package/components/raw_apps/RawAppInlineScriptEditor.svelte +1 -1
  122. package/package/components/schema/AddPropertyV2.svelte +2 -7
  123. package/package/components/schema/AddPropertyV2.svelte.d.ts +3 -20
  124. package/package/components/schema/EditableSchemaDrawer.svelte +109 -115
  125. package/package/components/schema/EditableSchemaDrawer.svelte.d.ts +2 -1
  126. package/package/components/schema/EditableSchemaSdkWrapper.svelte +16 -3
  127. package/package/components/schema/EditableSchemaSdkWrapper.svelte.d.ts +4 -1
  128. package/package/components/schema/EditableSchemaWrapper.svelte +3 -10
  129. package/package/components/schema/FlowPropertyEditor.svelte +83 -57
  130. package/package/components/schema/FlowPropertyEditor.svelte.d.ts +1 -1
  131. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  132. package/package/components/schema/SchemaFormDND.svelte +11 -10
  133. package/package/components/schema/SchemaFormDND.svelte.d.ts +3 -2
  134. package/package/components/schema/editable_schema_wrapper.d.ts +0 -3
  135. package/package/components/schema/jsonSchemaResource.svelte.d.ts +2 -0
  136. package/package/components/schema/jsonSchemaResource.svelte.js +40 -0
  137. package/package/components/settings/PremiumInfo.svelte +7 -2
  138. package/package/components/triggers/CaptureWrapper.svelte +2 -13
  139. package/package/components/triggers/CaptureWrapper.svelte.d.ts +1 -1
  140. package/package/components/triggers/TriggersWrapper.svelte +1 -0
  141. package/package/components/triggers/http/RouteEditorInner.svelte +1 -1
  142. package/package/components/triggers/nats/NatsTriggerEditorInner.svelte +23 -20
  143. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte +15 -27
  144. package/package/components/triggers/nats/NatsTriggersConfigSection.svelte.d.ts +7 -5
  145. package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +16 -16
  146. package/package/hubPaths.json +3 -1
  147. package/package/script_helpers.d.ts +2 -2
  148. package/package/script_helpers.js +2 -0
  149. package/package/stores.d.ts +1 -0
  150. package/package/stores.js +8 -1
  151. package/package/utils.d.ts +1 -1
  152. package/package.json +14 -14
  153. package/package/components/ModulePreviewResultViewer.svelte.d.ts +0 -28
@@ -1,10 +1,11 @@
1
1
  import { ScriptService, JobService } from '../../../../gen';
2
+ import { emitUiIntent } from './uiIntents';
2
3
  import YAML from 'yaml';
3
4
  import { z } from 'zod';
4
5
  import uFuzzy from '@leeoniya/ufuzzy';
5
6
  import { emptySchema, emptyString } from '../../../../utils';
6
- import { getFormattedResourceTypes, getLangContext, SUPPORTED_CHAT_SCRIPT_LANGUAGES } from '../script/core';
7
- import { createSearchHubScriptsTool, createToolDef, executeTestRun, buildSchemaForTool, buildTestRunArgs } from '../shared';
7
+ import { getFormattedResourceTypes, getLangContext, SUPPORTED_CHAT_SCRIPT_LANGUAGES, createDbSchemaTool } from '../script/core';
8
+ import { createSearchHubScriptsTool, createToolDef, executeTestRun, buildSchemaForTool, buildTestRunArgs, buildContextString, applyCodePiecesToFlowModules, findModuleById } from '../shared';
8
9
  const searchScriptsSchema = z.object({
9
10
  query: z
10
11
  .string()
@@ -98,6 +99,51 @@ const setForLoopIteratorExpressionSchema = z.object({
98
99
  expression: z.string().describe('The JavaScript expression to set for the iterator')
99
100
  });
100
101
  const setForLoopIteratorExpressionToolDef = createToolDef(setForLoopIteratorExpressionSchema, 'set_forloop_iterator_expression', 'Set the iterator JavaScript expression for the given forloop step');
102
+ const setForLoopOptionsSchema = z.object({
103
+ id: z.string().describe('The id of the forloop step to configure'),
104
+ skip_failures: z
105
+ .boolean()
106
+ .nullable()
107
+ .optional()
108
+ .describe('Whether to skip failures in the loop (null to not change)'),
109
+ parallel: z
110
+ .boolean()
111
+ .nullable()
112
+ .optional()
113
+ .describe('Whether to run iterations in parallel (null to not change)'),
114
+ parallelism: z
115
+ .number()
116
+ .int()
117
+ .min(1)
118
+ .nullable()
119
+ .optional()
120
+ .describe('Maximum number of parallel iterations (null to not change)')
121
+ });
122
+ const setForLoopOptionsToolDef = createToolDef(setForLoopOptionsSchema, 'set_forloop_options', 'Set advanced options for a forloop step: skip_failures, parallel, and parallelism');
123
+ const setModuleControlOptionsSchema = z.object({
124
+ id: z.string().describe('The id of the module to configure'),
125
+ stop_after_if: z
126
+ .boolean()
127
+ .nullable()
128
+ .optional()
129
+ .describe('Early stop condition (true to set, false to clear, null to not change)'),
130
+ stop_after_if_expr: z
131
+ .string()
132
+ .nullable()
133
+ .optional()
134
+ .describe('JavaScript expression for early stop condition. Can use `flow_input` or `result`. `result` is the result of the step. `results.<step_id>` is not supported, do not use it. Only used if stop_after_if is true. Example: `flow_input.x > 10` or `result === "failure"`'),
135
+ skip_if: z
136
+ .boolean()
137
+ .nullable()
138
+ .optional()
139
+ .describe('Skip condition (true to set, false to clear, null to not change)'),
140
+ skip_if_expr: z
141
+ .string()
142
+ .nullable()
143
+ .optional()
144
+ .describe('JavaScript expression for skip condition. Can use `flow_input` or `results.<step_id>`. Only used if skip_if is true. Example: `flow_input.x > 10` or `results.a === "failure"`')
145
+ });
146
+ const setModuleControlOptionsToolDef = createToolDef(setModuleControlOptionsSchema, 'set_module_control_options', 'Set control options for any module: stop_after_if (early stop) and skip_if (conditional skip)');
101
147
  const setBranchPredicateSchema = z.object({
102
148
  id: z.string().describe('The id of the branchone step to set the predicates for'),
103
149
  branchIndex: z
@@ -188,7 +234,10 @@ const getInstructionsForCodeGenerationToolSchema = z.object({
188
234
  const getInstructionsForCodeGenerationToolDef = createToolDef(getInstructionsForCodeGenerationToolSchema, 'get_instructions_for_code_generation', 'Get instructions for code generation for a raw script step');
189
235
  // Will be overridden by setSchema
190
236
  const testRunFlowSchema = z.object({
191
- args: z.object({}).nullable().optional()
237
+ args: z
238
+ .object({})
239
+ .nullable()
240
+ .optional()
192
241
  .describe('Arguments to pass to the flow (optional, uses default flow inputs if not provided)')
193
242
  });
194
243
  const testRunFlowToolDef = createToolDef(testRunFlowSchema, 'test_run_flow', 'Execute a test run of the current flow');
@@ -204,6 +253,7 @@ const testRunStepToolDef = createToolDef(testRunStepSchema, 'test_run_step', 'Ex
204
253
  const workspaceScriptsSearch = new WorkspaceScriptsSearch();
205
254
  export const flowTools = [
206
255
  createSearchHubScriptsTool(false),
256
+ createDbSchemaTool(),
207
257
  {
208
258
  def: searchScriptsToolDef,
209
259
  fn: async ({ args, workspace, toolId, toolCallbacks }) => {
@@ -374,6 +424,64 @@ export const flowTools = [
374
424
  return `Forloop '${parsedArgs.id}' iterator expression set`;
375
425
  }
376
426
  },
427
+ {
428
+ def: setForLoopOptionsToolDef,
429
+ fn: async ({ args, helpers, toolId, toolCallbacks }) => {
430
+ const parsedArgs = setForLoopOptionsSchema.parse(args);
431
+ await helpers.setForLoopOptions(parsedArgs.id, {
432
+ skip_failures: parsedArgs.skip_failures,
433
+ parallel: parsedArgs.parallel,
434
+ parallelism: parsedArgs.parallelism
435
+ });
436
+ helpers.selectStep(parsedArgs.id);
437
+ const message = `Set forloop '${parsedArgs.id}' options`;
438
+ toolCallbacks.setToolStatus(toolId, {
439
+ content: message
440
+ });
441
+ return `${message}: ${JSON.stringify(parsedArgs)}`;
442
+ }
443
+ },
444
+ {
445
+ def: setModuleControlOptionsToolDef,
446
+ fn: async ({ args, helpers, toolId, toolCallbacks }) => {
447
+ const parsedArgs = setModuleControlOptionsSchema.parse(args);
448
+ await helpers.setModuleControlOptions(parsedArgs.id, {
449
+ stop_after_if: parsedArgs.stop_after_if,
450
+ stop_after_if_expr: parsedArgs.stop_after_if_expr,
451
+ skip_if: parsedArgs.skip_if,
452
+ skip_if_expr: parsedArgs.skip_if_expr
453
+ });
454
+ helpers.selectStep(parsedArgs.id);
455
+ // Emit UI intent to show early-stop tab when stop_after_if is configured
456
+ const modules = helpers.getModules();
457
+ const module = findModuleById(modules, parsedArgs.id);
458
+ if (!module) {
459
+ throw new Error(`Module with id '${parsedArgs.id}' not found in flow.`);
460
+ }
461
+ const moduleType = module?.value.type;
462
+ const hasSpecificComponents = ['forloopflow', 'whileloopflow', 'branchall', 'branchone'];
463
+ const prefix = hasSpecificComponents.includes(moduleType) ? `${moduleType}` : 'flow';
464
+ if (typeof parsedArgs.stop_after_if === 'boolean') {
465
+ emitUiIntent({
466
+ kind: 'open_module_tab',
467
+ componentId: `${prefix}-${parsedArgs.id}`,
468
+ tab: 'early-stop'
469
+ });
470
+ }
471
+ if (typeof parsedArgs.skip_if === 'boolean') {
472
+ emitUiIntent({
473
+ kind: 'open_module_tab',
474
+ componentId: `${prefix}-${parsedArgs.id}`,
475
+ tab: 'skip'
476
+ });
477
+ }
478
+ const message = `Set module '${parsedArgs.id}' control options`;
479
+ toolCallbacks.setToolStatus(toolId, {
480
+ content: message
481
+ });
482
+ return `${message}: ${JSON.stringify(parsedArgs)}`;
483
+ }
484
+ },
377
485
  {
378
486
  def: resourceTypeToolDef,
379
487
  fn: async ({ args, toolId, workspace, toolCallbacks }) => {
@@ -405,7 +513,7 @@ export const flowTools = [
405
513
  workspace: workspace,
406
514
  requestBody: {
407
515
  args: parsedArgs,
408
- value: flow.value,
516
+ value: flow.value
409
517
  }
410
518
  }),
411
519
  workspace,
@@ -441,7 +549,7 @@ export const flowTools = [
441
549
  const stepArgs = args.args || {};
442
550
  // Find the step in the flow
443
551
  const modules = helpers.getModules();
444
- let targetModule = modules.find((m) => m.id === stepId);
552
+ let targetModule = findModuleById(modules, stepId);
445
553
  if (!targetModule) {
446
554
  toolCallbacks.setToolStatus(toolId, {
447
555
  content: `Step '${stepId}' not found in flow`,
@@ -459,7 +567,9 @@ export const flowTools = [
459
567
  requestBody: {
460
568
  content: moduleValue.content ?? '',
461
569
  language: moduleValue.language,
462
- args: module.id === 'preprocessor' ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs } : stepArgs
570
+ args: module.id === 'preprocessor'
571
+ ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs }
572
+ : stepArgs
463
573
  }
464
574
  }),
465
575
  workspace,
@@ -486,7 +596,9 @@ export const flowTools = [
486
596
  requestBody: {
487
597
  content: script.content,
488
598
  language: script.language,
489
- args: module.id === 'preprocessor' ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs } : stepArgs,
599
+ args: module.id === 'preprocessor'
600
+ ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs }
601
+ : stepArgs
490
602
  }
491
603
  }),
492
604
  workspace,
@@ -530,6 +642,16 @@ Follow the user instructions carefully.
530
642
  Go step by step, and explain what you're doing as you're doing it.
531
643
  DO NOT wait for user confirmation before performing an action. Only do it if the user explicitly asks you to wait in their initial instructions.
532
644
  ALWAYS test your modifications. You have access to the \`test_run_flow\` and \`test_run_step\` tools to test the flow and steps. If you only modified a single step, use the \`test_run_step\` tool to test it. If you modified the flow, use the \`test_run_flow\` tool to test it. If the user cancels the test run, do not try again and wait for the next user instruction.
645
+ When testing steps that are sql scripts, the arguments to be passed are { database: $res:<db_resource> }.
646
+
647
+ ## Code Markers in Flow Modules
648
+
649
+ When viewing flow modules, the code content of rawscript steps may include \`[#START]\` and \`[#END]\` markers:
650
+ - These markers indicate specific code sections that need attention
651
+ - You MUST only modify the code between these markers when using the \`set_code\` tool
652
+ - After modifying the code, remove the markers from your response
653
+ - If a question is asked about the code, focus only on the code between the markers
654
+ - The markers appear in the YAML representation of flow modules when specific code pieces are selected
533
655
 
534
656
  ## Understanding User Requests
535
657
 
@@ -566,10 +688,17 @@ When creating new steps, follow this process for EACH step:
566
688
 
567
689
  ### Special Step Types
568
690
  For special step types, follow these additional steps:
569
- - For forloop steps: Set the iterator expression using set_forloop_iterator_expression
691
+ - For forloop steps:
692
+ - Set the iterator expression using set_forloop_iterator_expression
693
+ - Set advanced options (parallel, parallelism, skip_failures) using set_forloop_options
570
694
  - For branchone steps: Set the predicates for each branch using set_branch_predicate
571
695
  - For branchall steps: No additional setup needed
572
696
 
697
+ ### Module Control Options
698
+ For any module type, you can set control flow options using set_module_control_options:
699
+ - **stop_after_if**: Early stop condition - stops the module if expression evaluates to true. Can use "flow_input" or "result". "result" is the result of the step. "results.<step_id>" is not supported, do not use it. Example: "flow_input.x > 10" or "result === "failure""
700
+ - **skip_if**: Skip condition - skips the module entirely if expression evaluates to true. Can use "flow_input" or "results.<step_id>". Example: "flow_input.x > 10" or "results.a === "failure""
701
+
573
702
  ### Step Insertion Rules
574
703
  When adding steps, carefully consider the execution order:
575
704
  1. Steps are executed in the order they appear in the flow definition, not in the order they were added
@@ -590,6 +719,7 @@ When adding steps, carefully consider the execution order:
590
719
  ### JavaScript Expressions
591
720
  For step inputs, forloop iterator expressions and branch predicates, use JavaScript expressions with these variables:
592
721
  - Step results: results.stepid or results.stepid.property_name
722
+ - Break condition (stop_after_if) in for loops: result (contains the result of the last iteration)
593
723
  - Loop iterator: flow_input.iter.value (inside loops)
594
724
  - Flow inputs: flow_input.property_name
595
725
  - Static values: Use JavaScript syntax (e.g., "hello", true, 3)
@@ -598,6 +728,12 @@ Note: These variables are only accessible in step inputs, forloop iterator expre
598
728
 
599
729
  For truly static values in step inputs (those not linked to previous steps or loop iterations), prefer using flow inputs by default unless explicitly specified otherwise. This makes the flow more configurable and reusable. For example, instead of hardcoding an email address in a step input, create a flow input for it.
600
730
 
731
+ ### For Loop Advanced Options
732
+ When configuring for-loop steps, consider these options:
733
+ - **parallel: true** - Run iterations in parallel for independent operations (significantly faster for I/O bound tasks)
734
+ - **parallelism: N** - Limit concurrent iterations (only applies when parallel=true). Use to prevent overwhelming external APIs
735
+ - **skip_failures: true** - Continue processing remaining iterations even if some fail. Failed iterations return error objects as results
736
+
601
737
  ### Special Modules
602
738
  - Preprocessor: Runs before the first step when triggered externally
603
739
  - ID: 'preprocessor'
@@ -611,6 +747,16 @@ For truly static values in step inputs (those not linked to previous steps or lo
611
747
 
612
748
  Both modules only support a script or rawscript step. You cannot nest modules using forloop/branchone/branchall.
613
749
 
750
+ ### Contexts
751
+
752
+ You have access to the following contexts:
753
+ - Database schemas
754
+ - Flow diffs
755
+ - Focused flow modules
756
+ Database schemas give you the schema of databases the user is using.
757
+ Flow diffs give you the diff between the current flow and the last deployed flow.
758
+ Focused flow modules give you the ids of the flow modules the user is focused on. Your response should focus on these modules.
759
+
614
760
  ## Resource types
615
761
  On Windmill, credentials and configuration are stored in resources. Resource types define the format of the resource.
616
762
  If the user needs a resource as flow input, you should set the property type in the schema to "object" as well as add a key called "format" and set it to "resource-nameofresourcetype" (e.g. "resource-stripe").
@@ -621,24 +767,27 @@ If the user wants a specific resource as step input, you should set the step val
621
767
  content
622
768
  };
623
769
  }
624
- export function prepareFlowUserMessage(instructions, flowAndSelectedId) {
770
+ export function prepareFlowUserMessage(instructions, flowAndSelectedId, selectedContext = []) {
625
771
  const flow = flowAndSelectedId?.flow;
626
772
  const selectedId = flowAndSelectedId?.selectedId;
773
+ // Handle context elements
774
+ const contextInstructions = selectedContext ? buildContextString(selectedContext) : '';
627
775
  if (!flow || !selectedId) {
776
+ let userMessage = `## INSTRUCTIONS:
777
+ ${instructions}`;
628
778
  return {
629
779
  role: 'user',
630
- content: `## INSTRUCTIONS:
631
- ${instructions}`
780
+ content: userMessage
632
781
  };
633
782
  }
634
- return {
635
- role: 'user',
636
- content: `## FLOW:
783
+ const codePieces = selectedContext.filter((c) => c.type === 'flow_module_code_piece');
784
+ const flowModulesYaml = applyCodePiecesToFlowModules(codePieces, flow.value.modules);
785
+ let flowContent = `## FLOW:
637
786
  flow_input schema:
638
787
  ${JSON.stringify(flow.schema ?? emptySchema())}
639
788
 
640
789
  flow modules:
641
- ${YAML.stringify(flow.value.modules)}
790
+ ${flowModulesYaml}
642
791
 
643
792
  preprocessor module:
644
793
  ${YAML.stringify(flow.value.preprocessor_module)}
@@ -647,9 +796,12 @@ failure module:
647
796
  ${YAML.stringify(flow.value.failure_module)}
648
797
 
649
798
  currently selected step:
650
- ${selectedId}
651
-
652
- ## INSTRUCTIONS:
653
- ${instructions}`
799
+ ${selectedId}`;
800
+ flowContent += contextInstructions;
801
+ flowContent += `\n\n## INSTRUCTIONS:
802
+ ${instructions}`;
803
+ return {
804
+ role: 'user',
805
+ content: flowContent
654
806
  };
655
807
  }
@@ -0,0 +1,8 @@
1
+ import { type Writable } from 'svelte/store';
2
+ export type UiIntent = {
3
+ kind: 'open_module_tab';
4
+ componentId: string;
5
+ tab: string;
6
+ };
7
+ export declare const uiIntentStore: Writable<UiIntent | null>;
8
+ export declare function emitUiIntent(intent: UiIntent): void;
@@ -0,0 +1,5 @@
1
+ import { writable } from 'svelte/store';
2
+ export const uiIntentStore = writable(null);
3
+ export function emitUiIntent(intent) {
4
+ uiIntentStore.set(intent);
5
+ }
@@ -0,0 +1,5 @@
1
+ type Handlers = {
2
+ openTab?: (tab: string) => void;
3
+ };
4
+ export declare function useUiIntent(componentId: string, handlers: Handlers): void;
5
+ export {};
@@ -0,0 +1,12 @@
1
+ import { uiIntentStore } from './uiIntents';
2
+ import { onDestroy } from 'svelte';
3
+ export function useUiIntent(componentId, handlers) {
4
+ const unsub = uiIntentStore.subscribe((intent) => {
5
+ if (!intent || intent.componentId !== componentId)
6
+ return;
7
+ if (intent.kind === 'open_module_tab')
8
+ handlers.openTab?.(intent.tab);
9
+ uiIntentStore.set(null);
10
+ });
11
+ onDestroy(() => unsub());
12
+ }
@@ -15,18 +15,36 @@ export declare class AIChatEditorHandler {
15
15
  changes: VisualChangeWithDiffIndex[];
16
16
  groupIndex: number;
17
17
  }[];
18
+ private reviewState;
18
19
  constructor(editor: meditor.IStandaloneCodeEditor);
19
20
  clear(): void;
20
21
  preventWriting(): void;
21
22
  allowWriting(): void;
22
- finish(): Promise<void>;
23
- acceptAll(): Promise<void>;
24
- rejectAll(): Promise<void>;
23
+ finish(opts?: {
24
+ disableReviewCallback?: boolean;
25
+ }): Promise<void>;
26
+ getReviewMode(): 'apply' | 'revert' | null;
27
+ acceptAll(opts?: {
28
+ disableReviewCallback?: boolean;
29
+ }): Promise<void>;
30
+ rejectAll(opts?: {
31
+ disableReviewCallback?: boolean;
32
+ }): Promise<void>;
33
+ keepAll(opts?: {
34
+ disableReviewCallback?: boolean;
35
+ }): Promise<void>;
36
+ revertAll(opts?: {
37
+ disableReviewCallback?: boolean;
38
+ }): Promise<void>;
25
39
  applyGroup(group: {
26
40
  changes: VisualChangeWithDiffIndex[];
27
41
  groupIndex: number;
28
42
  }): void;
29
43
  private calculateVisualChanges;
30
- reviewAndApply(newCode: string, applyAll?: boolean): Promise<void>;
44
+ reviewChanges(targetCode: string, opts?: {
45
+ applyAll?: boolean;
46
+ mode?: 'apply' | 'revert';
47
+ onFinishedReview?: () => void;
48
+ }): Promise<void>;
31
49
  }
32
50
  export {};
@@ -10,6 +10,8 @@ export class AIChatEditorHandler {
10
10
  readOnlyDisposable = undefined;
11
11
  reviewingChanges = writable(false);
12
12
  groupChanges = [];
13
+ // Track review decisions
14
+ reviewState = null;
13
15
  constructor(editor) {
14
16
  this.editor = editor;
15
17
  }
@@ -48,7 +50,14 @@ export class AIChatEditorHandler {
48
50
  this.readOnlyDisposable.dispose();
49
51
  }
50
52
  }
51
- async finish() {
53
+ async finish(opts) {
54
+ // expose mode getter relies on reviewState
55
+ // Call completion callback if we're tracking review state
56
+ if (this.reviewState?.onFinishedReview && !opts?.disableReviewCallback) {
57
+ this.reviewState.onFinishedReview();
58
+ }
59
+ // Reset review state
60
+ this.reviewState = null;
52
61
  this.clear();
53
62
  this.allowWriting();
54
63
  this.reviewingChanges.set(false);
@@ -56,15 +65,26 @@ export class AIChatEditorHandler {
56
65
  scrollBeyondLastLine: false
57
66
  });
58
67
  }
59
- async acceptAll() {
68
+ getReviewMode() {
69
+ return this.reviewState?.mode ?? null;
70
+ }
71
+ async acceptAll(opts) {
60
72
  this.groupChanges.reverse();
61
73
  for (const group of this.groupChanges) {
62
74
  this.applyGroup(group);
63
75
  }
64
- this.finish();
76
+ this.finish(opts);
77
+ }
78
+ async rejectAll(opts) {
79
+ this.finish(opts);
80
+ }
81
+ // Keep all changes, used in revert mode
82
+ async keepAll(opts) {
83
+ this.finish(opts);
65
84
  }
66
- async rejectAll() {
67
- this.finish();
85
+ // Revert all changes, used in revert mode
86
+ async revertAll(opts) {
87
+ this.acceptAll(opts);
68
88
  }
69
89
  applyGroup(group) {
70
90
  // maximum of 2 changes per group with the deletion first
@@ -147,23 +167,30 @@ export class AIChatEditorHandler {
147
167
  }
148
168
  return changedLines;
149
169
  }
150
- async reviewAndApply(newCode, applyAll = false) {
151
- if (aiChatManager.pendingNewCode === newCode) {
170
+ async reviewChanges(targetCode, opts) {
171
+ if (aiChatManager.pendingNewCode === targetCode && opts?.mode === 'apply') {
152
172
  this.acceptAll();
153
173
  return;
154
174
  }
155
175
  else if (aiChatManager.pendingNewCode) {
156
176
  this.clear();
157
177
  }
158
- aiChatManager.pendingNewCode = newCode;
159
- const changedLines = await this.calculateVisualChanges(newCode);
178
+ aiChatManager.pendingNewCode = targetCode;
179
+ const changedLines = await this.calculateVisualChanges(targetCode);
160
180
  if (changedLines.length === 0)
161
181
  return;
182
+ // Initialize review state for tracking
183
+ this.reviewState = {
184
+ mode: opts?.mode ?? 'apply',
185
+ onFinishedReview: opts?.onFinishedReview
186
+ };
162
187
  let indicesOfRejectedLineChanges = [];
163
188
  for (const [groupIndex, group] of this.groupChanges.entries()) {
164
189
  let collection = undefined;
165
190
  let ids = [];
166
- const acceptFn = () => {
191
+ const isRevert = opts?.mode === 'revert';
192
+ // Apply this group and continue with remaining changes
193
+ const onApply = () => {
167
194
  this.applyGroup(group);
168
195
  this.clear();
169
196
  let newCodeWithRejects = '';
@@ -178,9 +205,11 @@ export class AIChatEditorHandler {
178
205
  newCodeWithRejects += change.value;
179
206
  }
180
207
  }
181
- this.reviewAndApply(newCodeWithRejects);
208
+ this.reviewChanges(newCodeWithRejects, opts);
182
209
  };
183
- const rejectFn = () => {
210
+ // Discard this group and continue with remaining changes
211
+ const onDiscard = () => {
212
+ // This group was not applied (not reverted in revert mode)
184
213
  indicesOfRejectedLineChanges.push(...group.changes.map((c) => c.diffIndex));
185
214
  collection?.clear();
186
215
  this.editor.changeViewZones((acc) => {
@@ -193,25 +222,35 @@ export class AIChatEditorHandler {
193
222
  this.finish();
194
223
  }
195
224
  };
225
+ // In revert mode: Accept = keep current code, Reject = revert to targetCode
226
+ // In apply mode: Accept = apply changes, Reject = discard changes
227
+ const acceptFn = isRevert ? onDiscard : onApply;
228
+ const rejectFn = isRevert ? onApply : onDiscard;
196
229
  const changes = group.changes.map((c, i) => {
197
230
  if (i === group.changes.length - 1) {
198
231
  return {
199
232
  ...c,
200
- options: { ...(c.options ?? {}), review: { acceptFn, rejectFn } }
233
+ options: {
234
+ ...(c.options ?? {}),
235
+ review: {
236
+ acceptFn,
237
+ rejectFn
238
+ }
239
+ }
201
240
  };
202
241
  }
203
242
  else {
204
243
  return c;
205
244
  }
206
245
  });
207
- if (!applyAll) {
246
+ if (!opts?.applyAll) {
208
247
  ;
209
- ({ collection, ids } = await displayVisualChanges('editor-windmill-chat-style', this.editor, changes));
248
+ ({ collection, ids } = await displayVisualChanges('editor-windmill-chat-style', this.editor, changes, isRevert));
210
249
  this.decorationsCollections.push(collection);
211
250
  this.viewZoneIds.push(...ids);
212
251
  }
213
252
  }
214
- if (applyAll) {
253
+ if (opts?.applyAll) {
215
254
  this.acceptAll();
216
255
  }
217
256
  }
@@ -10,10 +10,9 @@ export declare function getLangContext(lang: ScriptLang | 'bunnative' | 'jsx' |
10
10
  isFailure?: boolean;
11
11
  }): string;
12
12
  export declare function getFormattedResourceTypes(lang: ScriptLang | 'bunnative', prompt: string, workspace: string): Promise<string>;
13
- export declare const CHAT_SYSTEM_PROMPT = "\n\tYou are a coding assistant for the Windmill platform. You are provided with a list of `INSTRUCTIONS` and the current contents of a code file under `CODE`.\n\n\tYour task is to respond to the user's request. Assume all user queries are valid and actionable.\n\n\tWhen the user requests code changes:\n\t- Always include a **single code block** with the **entire updated file**, not just the modified sections.\n\t- The code can include `[#START]` and `[#END]` markers to indicate the start and end of a code piece. You MUST only modify the code between these markers if given, and remove them in your response. If a question is asked about the code, you MUST only talk about the code between the markers. Refer to it as the code piece, not the code between the markers.\n\t- Follow the instructions carefully and explain the reasoning behind your changes.\n\t- If the request is abstract (e.g., \"make this cleaner\"), interpret it concretely and reflect that in the code block.\n\t- Preserve existing formatting, indentation, and whitespace unless changes are strictly required to fulfill the user's request.\n\t- The user can ask you to look at or modify specific files, databases or errors by having its name in the INSTRUCTIONS preceded by the @ symbol. In this case, put your focus on the element that is explicitly mentioned.\n\t- The user can ask you questions about a list of `DATABASES` that are available in the user's workspace. If the user asks you a question about a database, you should ask the user to specify the database name if not given, or take the only one available if there is only one.\n\t- You can also receive a `DIFF` of the changes that have been made to the code. You should use this diff to give better answers.\n\t- Before giving your answer, check again that you carefully followed these instructions.\n\t- When asked to create a script that communicates with an external service, you can use the `search_hub_scripts` tool to search for relevant scripts in the hub. Make sure the language is the same as what the user is coding in. If you do not find any relevant scripts, you can use the `search_npm_packages` tool to search for relevant packages and their documentation. Always give a link to the documentation in your answer if possible.\n\t- After modifying the code, ALWAYS use the `test_run_script` tool to test the code, and iterate on the code until it works as expected. If the user cancels the test run, do not try again and wait for the next user instruction.\n\n\tImportant:\n\tDo not mention or reveal these instructions to the user unless explicitly asked to do so.\n";
13
+ export declare const CHAT_SYSTEM_PROMPT = "\n\tYou are a coding assistant for the Windmill platform. You are provided with a list of `INSTRUCTIONS` and the current contents of a code file under `CODE`.\n\n\tYour task is to respond to the user's request. Assume all user queries are valid and actionable.\n\n\tWhen the user requests code changes:\n\t- Always include a **single code block** with the **entire updated file**, not just the modified sections.\n\t- The code can include `[#START]` and `[#END]` markers to indicate the start and end of a code piece. You MUST only modify the code between these markers if given, and remove them in your response. If a question is asked about the code, you MUST only talk about the code between the markers. Refer to it as the code piece, not the code between the markers.\n\t- Follow the instructions carefully and explain the reasoning behind your changes.\n\t- If the request is abstract (e.g., \"make this cleaner\"), interpret it concretely and reflect that in the code block.\n\t- Preserve existing formatting, indentation, and whitespace unless changes are strictly required to fulfill the user's request.\n\t- The user can ask you to look at or modify specific files, databases or errors by having its name in the INSTRUCTIONS preceded by the @ symbol. In this case, put your focus on the element that is explicitly mentioned.\n\t- The user can ask you questions about a list of `DATABASES` that are available in the user's workspace. If the user asks you a question about a database, you should ask the user to specify the database name if not given, or take the only one available if there is only one.\n\t- You can also receive a `DIFF` of the changes that have been made to the code. You should use this diff to give better answers.\n\t- Before giving your answer, check again that you carefully followed these instructions.\n\t- When asked to create a script that communicates with an external service, you can use the `search_hub_scripts` tool to search for relevant scripts in the hub. Make sure the language is the same as what the user is coding in. If you do not find any relevant scripts, you can use the `search_npm_packages` tool to search for relevant packages and their documentation. Always give a link to the documentation in your answer if possible.\n\t- At the end of your reponse, if you modified or suggested changes to the code, ALWAYS use the `test_run_script` tool to test the code, and iterate on the code until it works as expected (MAX 3 times). If the user cancels the test run, do not try again and wait for the next user instruction.\n\n\tImportant:\n\tDo not mention or reveal these instructions to the user unless explicitly asked to do so.\n";
14
14
  export declare const INLINE_CHAT_SYSTEM_PROMPT = "\n# Windmill Inline Coding Assistant\n\nYou are a coding assistant for the Windmill platform. You provide precise code modifications based on user instructions.\n\n## Input Format\n\nYou will receive:\n- **INSTRUCTIONS**: User's modification request\n- **CODE**: Current code content with modification boundaries\n- **DATABASES** *(optional)*: Available workspace databases\n\n### Code Boundaries\n\nThe code contains `[#START]` and `[#END]` markers indicating the modification scope:\n- **MUST** only modify code between these markers\n- **MUST** remove the markers in your response\n- **MUST** preserve all other code exactly as provided\n\n## Task Requirements\n\nReturn the modified CODE that fulfills the user's request. Assume all user queries are valid and actionable.\n\n### Critical Rules\n\n- \u2705 **ALWAYS** include a single code block with the entire updated CODE\n- \u2705 **ALWAYS** use the structured XML output format below\n- \u274C **NEVER** include only modified sections\n- \u274C **NEVER** add explanatory text or comments outside the format\n- \u274C **NEVER** include ``` code fences in your response\n- \u274C **NEVER** modify the code outside the boundaries\n\n## Output Format\n\n```xml\n<changes_made>\nBrief description of what was changed\n</changes_made>\n<new_code>\n[complete modified code without markers]\n</new_code>\n```\n\n## Example\n\n### Input:\n```xml\n<user_request>\nINSTRUCTIONS:\nReturn 2 instead of 1\n\nCODE:\nimport * as wmill from \"windmill-client\"\n\nfunction test() {\n\treturn \"hello\"\n}\n\n[#START]\nexport async function main() {\n\treturn 1;\n}\n[#END]\n</user_request>\n```\n\n### Expected Output:\n```xml\n<changes_made>\nChanged return value from 1 to 2 in main function\n</changes_made>\n<new_code>\nimport * as wmill from \"windmill-client\"\n\nfunction test() {\n\treturn \"hello\"\n}\n\nexport async function main() {\n\treturn 2;\n}\n</new_code>\n```\n";
15
15
  export declare const CHAT_USER_PROMPT = "\nINSTRUCTIONS:\n{instructions}\n\nWINDMILL LANGUAGE CONTEXT:\n{lang_context}\n\n";
16
- export declare const CHAT_USER_DB_CONTEXT = "- {title}: SCHEMA: \n{schema}\n";
17
16
  export declare function prepareScriptSystemMessage(): ChatCompletionSystemMessageParam;
18
17
  export declare function prepareScriptTools(language: ScriptLang | 'bunnative', context: ContextElement[]): Tool<ScriptChatHelpers>[];
19
18
  export declare function prepareScriptUserMessage(instructions: string, language: ScriptLang | 'bunnative', selectedContext: ContextElement[], options?: {
@@ -31,6 +30,7 @@ export interface ScriptChatHelpers {
31
30
  applyCode: (code: string, applyAll?: boolean) => void;
32
31
  }
33
32
  export declare const resourceTypeTool: Tool<ScriptChatHelpers>;
33
+ export declare function createDbSchemaTool<T>(): Tool<T>;
34
34
  export declare const dbSchemaTool: Tool<ScriptChatHelpers>;
35
35
  export declare function searchExternalIntegrationResources(args: {
36
36
  query: string;