windmill-components 1.531.0 → 1.532.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/package/components/ArgInput.svelte +44 -1
  2. package/package/components/EditableSchemaForm.svelte +27 -18
  3. package/package/components/EditableSchemaForm.svelte.d.ts +1 -0
  4. package/package/components/Editor.svelte +2 -2
  5. package/package/components/Editor.svelte.d.ts +1 -0
  6. package/package/components/EditorBar.svelte +2 -2
  7. package/package/components/EditorBar.svelte.d.ts +1 -0
  8. package/package/components/FieldHeader.svelte +1 -1
  9. package/package/components/FlowWrapper.svelte +3 -2
  10. package/package/components/ModuleTest.svelte +4 -1
  11. package/package/components/ResourceEditor.svelte +4 -0
  12. package/package/components/ScriptEditor.svelte +1 -0
  13. package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
  14. package/package/components/copilot/FlowInlineScriptAIButton.svelte +4 -2
  15. package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +4 -1
  16. package/package/components/copilot/autocomplete/Autocompletor.js +0 -2
  17. package/package/components/copilot/chat/AIChat.svelte +2 -4
  18. package/package/components/copilot/chat/AIChatInput.svelte +4 -3
  19. package/package/components/copilot/chat/AIChatManager.svelte.js +21 -9
  20. package/package/components/copilot/chat/AvailableContextList.svelte +115 -24
  21. package/package/components/copilot/chat/AvailableContextList.svelte.d.ts +1 -0
  22. package/package/components/copilot/chat/ContextElementBadge.svelte +31 -15
  23. package/package/components/copilot/chat/ContextElementBadge.svelte.d.ts +5 -20
  24. package/package/components/copilot/chat/ContextManager.svelte.d.ts +15 -2
  25. package/package/components/copilot/chat/ContextManager.svelte.js +102 -15
  26. package/package/components/copilot/chat/ContextTextarea.svelte +1 -1
  27. package/package/components/copilot/chat/context.d.ts +14 -1
  28. package/package/components/copilot/chat/context.js +1 -0
  29. package/package/components/copilot/chat/flow/FlowAIChat.svelte +1 -1
  30. package/package/components/copilot/chat/flow/core.d.ts +2 -1
  31. package/package/components/copilot/chat/flow/core.js +52 -18
  32. package/package/components/copilot/chat/script/core.d.ts +2 -2
  33. package/package/components/copilot/chat/script/core.js +51 -122
  34. package/package/components/copilot/chat/shared.d.ts +13 -2
  35. package/package/components/copilot/chat/shared.js +155 -4
  36. package/package/components/flows/FlowEditor.svelte +12 -0
  37. package/package/components/flows/FlowModuleIcon.svelte +39 -0
  38. package/package/components/flows/FlowModuleIcon.svelte.d.ts +10 -0
  39. package/package/components/flows/content/FlowModuleComponent.svelte +2 -0
  40. package/package/components/flows/map/MapItem.svelte +8 -39
  41. package/package/components/schema/FlowPropertyEditor.svelte +75 -17
  42. package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
  43. package/package/components/schema/jsonSchemaResource.svelte.d.ts +2 -0
  44. package/package/components/schema/jsonSchemaResource.svelte.js +40 -0
  45. package/package/utils.d.ts +1 -1
  46. package/package.json +13 -13
@@ -6,42 +6,44 @@ import { json } from 'svelte-highlight/languages';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import { formatGraphqlSchema, formatSchema } from '../../apps/components/display/dbtable/utils';
8
8
  import ObjectViewer from '../../propertyPicker/ObjectViewer.svelte';
9
- import { createEventDispatcher } from 'svelte';
10
9
  import HighlightCode from '../../HighlightCode.svelte';
11
- export let contextElement;
12
- export let deletable = false;
10
+ import FlowModuleIcon from '../../flows/FlowModuleIcon.svelte';
11
+ let { contextElement, deletable = false, onDelete } = $props();
13
12
  const icon = ContextIconMap[contextElement.type];
14
- let showDelete = false;
15
- const dispatch = createEventDispatcher();
13
+ let showDelete = $state(false);
14
+ const isDeletable = $derived(deletable && contextElement.deletable !== false);
16
15
  </script>
17
16
 
18
17
  <Popover>
19
- <svelte:fragment slot="trigger">
18
+ {#snippet trigger()}
20
19
  <div
21
20
  class={twMerge(
22
21
  'border rounded-md px-1 py-0.5 flex flex-row items-center gap-1 text-tertiary text-xs cursor-default hover:bg-surface-hover hover:cursor-pointer max-w-48 bg-surface'
23
22
  )}
24
- on:mouseenter={() => (showDelete = true)}
25
- on:mouseleave={() => (showDelete = false)}
23
+ onmouseenter={() => (showDelete = true)}
24
+ onmouseleave={() => (showDelete = false)}
26
25
  aria-label="Context element"
27
26
  role="button"
28
27
  tabindex={0}
29
28
  >
30
- <button on:click={() => dispatch('delete')} class:cursor-default={!deletable}>
31
- {#if showDelete && deletable}
29
+ <button onclick={isDeletable ? onDelete : undefined} class:cursor-default={!isDeletable}>
30
+ {#if showDelete && isDeletable}
32
31
  <X size={16} />
32
+ {:else if contextElement.type === 'flow_module'}
33
+ <FlowModuleIcon module={contextElement as FlowModule} size={16} />
33
34
  {:else}
34
- <svelte:component this={icon} size={16} />
35
+ {@const SvelteComponent = icon}
36
+ <SvelteComponent size={16} />
35
37
  {/if}
36
38
  </button>
37
39
  <span class="truncate">
38
- {contextElement.type === 'diff'
40
+ {contextElement.type === 'diff' || contextElement.type === 'flow_module'
39
41
  ? contextElement.title.replace(/_/g, ' ')
40
42
  : contextElement.title}
41
43
  </span>
42
44
  </div>
43
- </svelte:fragment>
44
- <svelte:fragment slot="content">
45
+ {/snippet}
46
+ {#snippet content()}
45
47
  {#if contextElement.type === 'error'}
46
48
  <div class="max-w-96 max-h-[300px] text-xs overflow-auto">
47
49
  <Highlight language={json} code={contextElement.content} class="w-full p-2" />
@@ -71,6 +73,20 @@ const dispatch = createEventDispatcher();
71
73
  class="w-full p-2 "
72
74
  />
73
75
  </div>
76
+ {:else if contextElement.type === 'flow_module'}
77
+ {#if contextElement.value.content}
78
+ <div class="p-2 max-w-96 max-h-[300px] text-xs overflow-auto">
79
+ <HighlightCode
80
+ language={contextElement.value.language}
81
+ code={contextElement.value.content}
82
+ class="w-full p-2 "
83
+ />
84
+ </div>
85
+ {:else}
86
+ <div class="p-2 max-w-96 max-h-[300px] text-xs overflow-auto">
87
+ <div class="text-tertiary">{contextElement.title}</div>
88
+ </div>
89
+ {/if}
74
90
  {/if}
75
- </svelte:fragment>
91
+ {/snippet}
76
92
  </Popover>
@@ -1,24 +1,9 @@
1
1
  import { type ContextElement } from './context';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const ContextElementBadge: $$__sveltets_2_IsomorphicComponent<{
2
+ interface Props {
16
3
  contextElement: ContextElement;
17
4
  deletable?: boolean;
18
- }, {
19
- delete: CustomEvent<void>;
20
- } & {
21
- [evt: string]: CustomEvent<any>;
22
- }, {}, {}, string>;
23
- type ContextElementBadge = InstanceType<typeof ContextElementBadge>;
5
+ onDelete?: () => void;
6
+ }
7
+ declare const ContextElementBadge: import("svelte").Component<Props, {}, "">;
8
+ type ContextElementBadge = ReturnType<typeof ContextElementBadge>;
24
9
  export default ContextElementBadge;
@@ -1,7 +1,9 @@
1
- import { type ScriptLang } from '../../../gen';
1
+ import { type Flow, type ScriptLang } from '../../../gen';
2
2
  import { type DBSchemas } from '../../../stores';
3
3
  import type { ContextElement } from './context';
4
+ import type { FlowModule } from '../../../gen';
4
5
  import type { DisplayMessage } from './shared';
6
+ import type { ExtendedOpenFlow } from '../../flows/types';
5
7
  export interface ScriptOptions {
6
8
  lang: ScriptLang | 'bunnative';
7
9
  code: string;
@@ -12,6 +14,13 @@ export interface ScriptOptions {
12
14
  lastDeployedCode?: string;
13
15
  diffMode: boolean;
14
16
  }
17
+ export interface FlowOptions {
18
+ currentFlow: ExtendedOpenFlow;
19
+ lastDeployedFlow?: Flow;
20
+ path: string | undefined;
21
+ modules: FlowModule[];
22
+ lastSavedFlow?: Flow;
23
+ }
15
24
  export default class ContextManager {
16
25
  private selectedContext;
17
26
  private availableContext;
@@ -21,11 +30,13 @@ export default class ContextManager {
21
30
  private refreshDbResources;
22
31
  private getSelectedDBSchema;
23
32
  private getContextCodePath;
33
+ updateAvailableContextForFlow(flowOptions: FlowOptions, dbSchemas: DBSchemas, workspace: string, toolSupport: boolean, currentlySelectedContext: ContextElement[]): Promise<void>;
24
34
  updateAvailableContext(scriptOptions: ScriptOptions, dbSchemas: DBSchemas, workspace: string, toolSupport: boolean, currentlySelectedContext: ContextElement[]): Promise<void>;
25
35
  getSelectedContext(): ContextElement[];
26
36
  setSelectedContext(newSelectedContext: ContextElement[]): void;
27
37
  getAvailableContext(): ContextElement[];
28
- addSelectedLinesToContext(lines: string, startLine: number, endLine: number): void;
38
+ setScriptOptions(scriptOptions: ScriptOptions): void;
39
+ addSelectedLinesToContext(lines: string, startLine: number, endLine: number, moduleId?: string): void;
29
40
  setFixContext(): void;
30
41
  setAskAiContext(options: {
31
42
  withCode?: boolean;
@@ -36,4 +47,6 @@ export default class ContextManager {
36
47
  addBackCode?: boolean;
37
48
  }): void;
38
49
  static updateDisplayMessages(displayMessages: DisplayMessage[], dbSchemas: DBSchemas): DisplayMessage[];
50
+ setSelectedModuleContext(moduleId: string | undefined, availableContext: ContextElement[] | undefined): void;
51
+ clearContext(): void;
39
52
  }
@@ -33,14 +33,82 @@ export default class ContextManager {
33
33
  '.' +
34
34
  langToExt(scriptLangToEditorLang(scriptOptions.lang)));
35
35
  }
36
+ async updateAvailableContextForFlow(flowOptions, dbSchemas, workspace, toolSupport, currentlySelectedContext) {
37
+ try {
38
+ if (this.workspace !== workspace) {
39
+ await this.refreshDbResources(workspace);
40
+ this.workspace = workspace;
41
+ }
42
+ let newAvailableContext = [];
43
+ // Add diff context if we have a deployed flow version
44
+ const deployedFlowString = JSON.stringify(flowOptions.lastDeployedFlow, null, 2);
45
+ const savedFlowString = JSON.stringify(flowOptions.lastSavedFlow, null, 2);
46
+ const currentFlowString = JSON.stringify(flowOptions.currentFlow, null, 2);
47
+ if (currentFlowString && deployedFlowString && deployedFlowString !== currentFlowString) {
48
+ newAvailableContext.push({
49
+ type: 'diff',
50
+ title: 'diff_with_last_deployed_version',
51
+ content: deployedFlowString,
52
+ diff: diffLines(deployedFlowString, currentFlowString),
53
+ lang: 'graphql' // irrelevant, but needed for the diff component
54
+ });
55
+ }
56
+ if (currentFlowString && savedFlowString && savedFlowString !== currentFlowString) {
57
+ newAvailableContext.push({
58
+ type: 'diff',
59
+ title: 'diff_with_last_saved_draft',
60
+ content: savedFlowString,
61
+ diff: diffLines(savedFlowString, currentFlowString),
62
+ lang: 'graphql' // irrelevant, but needed for the diff component
63
+ });
64
+ }
65
+ for (const module of flowOptions.modules) {
66
+ newAvailableContext.push({
67
+ type: 'flow_module',
68
+ id: module.id,
69
+ title: `module_[${module.id}]`,
70
+ value: {
71
+ language: 'language' in module.value ? module.value.language : 'bunnative',
72
+ path: 'path' in module.value ? module.value.path : '',
73
+ content: 'content' in module.value ? module.value.content : '',
74
+ type: module.value.type
75
+ }
76
+ });
77
+ }
78
+ if (toolSupport) {
79
+ for (const d of this.dbResources) {
80
+ const loadedSchema = dbSchemas[d.path];
81
+ newAvailableContext.push({
82
+ type: 'db',
83
+ title: d.path,
84
+ // If the db is already fetched, add the schema to the context
85
+ ...(loadedSchema ? { schema: loadedSchema } : {})
86
+ });
87
+ }
88
+ }
89
+ let newSelectedContext = [...currentlySelectedContext];
90
+ // Filter selected context to only include available items
91
+ newSelectedContext = newSelectedContext
92
+ .filter((c) => newAvailableContext.some((ac) => ac.type === c.type && ac.title === c.title))
93
+ .map((c) => c.type === 'db' && dbSchemas[c.title]
94
+ ? {
95
+ ...c,
96
+ schema: dbSchemas[c.title]
97
+ }
98
+ : c);
99
+ this.availableContext = newAvailableContext;
100
+ this.selectedContext = newSelectedContext;
101
+ }
102
+ catch (err) {
103
+ console.error('Could not update available context for flow', err);
104
+ }
105
+ }
36
106
  async updateAvailableContext(scriptOptions, dbSchemas, workspace, toolSupport, currentlySelectedContext) {
37
107
  try {
38
- let firstTime = !this.workspace;
39
108
  if (this.workspace !== workspace) {
40
109
  await this.refreshDbResources(workspace);
41
110
  this.workspace = workspace;
42
111
  }
43
- this.scriptOptions = scriptOptions;
44
112
  let newAvailableContext = [
45
113
  {
46
114
  type: 'code',
@@ -89,16 +157,15 @@ export default class ContextManager {
89
157
  ];
90
158
  }
91
159
  let newSelectedContext = [...currentlySelectedContext];
92
- if (firstTime) {
93
- newSelectedContext = [
94
- {
95
- type: 'code',
96
- title: this.getContextCodePath(scriptOptions) ?? '',
97
- content: scriptOptions.code,
98
- lang: scriptOptions.lang
99
- }
100
- ];
101
- }
160
+ newSelectedContext = [
161
+ {
162
+ type: 'code',
163
+ title: this.getContextCodePath(scriptOptions) ?? '',
164
+ content: scriptOptions.code,
165
+ lang: scriptOptions.lang,
166
+ deletable: false
167
+ }
168
+ ];
102
169
  const db = this.getSelectedDBSchema(scriptOptions, dbSchemas);
103
170
  if (db &&
104
171
  !newSelectedContext.find((c) => c.type === 'db' && db && c.title === db.resource) &&
@@ -144,16 +211,20 @@ export default class ContextManager {
144
211
  getAvailableContext() {
145
212
  return this.availableContext;
146
213
  }
147
- addSelectedLinesToContext(lines, startLine, endLine) {
214
+ setScriptOptions(scriptOptions) {
215
+ this.scriptOptions = scriptOptions;
216
+ }
217
+ addSelectedLinesToContext(lines, startLine, endLine, moduleId) {
218
+ const title = moduleId ? `[${moduleId}] L${startLine}-L${endLine}` : `L${startLine}-L${endLine}`;
148
219
  if (!this.scriptOptions ||
149
- this.selectedContext.find((c) => c.type === 'code_piece' && c.title === `L${startLine}-L${endLine}`)) {
220
+ this.selectedContext.find((c) => c.type === 'code_piece' && c.title === title)) {
150
221
  return;
151
222
  }
152
223
  this.selectedContext = [
153
224
  ...this.selectedContext,
154
225
  {
155
226
  type: 'code_piece',
156
- title: `L${startLine}-L${endLine}`,
227
+ title: title,
157
228
  startLine,
158
229
  endLine,
159
230
  content: lines,
@@ -217,4 +288,20 @@ export default class ContextManager {
217
288
  : undefined
218
289
  }));
219
290
  }
291
+ setSelectedModuleContext(moduleId, availableContext) {
292
+ if (availableContext && moduleId) {
293
+ const module = availableContext.find((c) => c.type === 'flow_module' && c.id === moduleId);
294
+ if (module &&
295
+ !this.selectedContext.find((c) => c.type === 'flow_module' && c.id === moduleId)) {
296
+ this.selectedContext = this.selectedContext.filter((c) => c.type !== 'flow_module');
297
+ this.selectedContext = [module, ...this.selectedContext];
298
+ }
299
+ }
300
+ else if (!moduleId) {
301
+ this.selectedContext = this.selectedContext.filter((c) => c.type !== 'flow_module');
302
+ }
303
+ }
304
+ clearContext() {
305
+ this.selectedContext = [];
306
+ }
220
307
  }
@@ -119,7 +119,7 @@ function getCaretCoordinates(element, position) {
119
119
  return coordinates;
120
120
  }
121
121
  function getHighlightedText(text) {
122
- return text.replace(/@[\w/.-]+/g, (match) => {
122
+ return text.replace(/@[\w/.\-\[\]]+/g, (match) => {
123
123
  const contextElement = availableContext.find((c) => c.title === match.slice(1));
124
124
  if (contextElement) {
125
125
  return `<span class="bg-black dark:bg-white text-white dark:text-black z-10">${match}</span>`;
@@ -40,5 +40,18 @@ export interface CodePieceElement {
40
40
  title: string;
41
41
  lang: ScriptLang | 'bunnative';
42
42
  }
43
- export type ContextElement = CodeElement | ErrorElement | DBElement | DiffElement | CodePieceElement;
43
+ export interface FlowModule {
44
+ type: 'flow_module';
45
+ id: string;
46
+ title: string;
47
+ value: {
48
+ language?: ScriptLang | 'bunnative';
49
+ path?: string;
50
+ content?: string;
51
+ type: string;
52
+ };
53
+ }
54
+ export type ContextElement = (CodeElement | ErrorElement | DBElement | DiffElement | CodePieceElement | FlowModule) & {
55
+ deletable?: boolean;
56
+ };
44
57
  export {};
@@ -7,4 +7,5 @@ export const ContextIconMap = {
7
7
  db: Database,
8
8
  diff: Diff,
9
9
  code_piece: Code
10
+ // flow_module type is handled with FlowModuleIcon
10
11
  };
@@ -9,7 +9,7 @@ import { loadSchemaFromModule } from '../../../flows/flowInfers';
9
9
  import { aiChatManager } from '../AIChatManager.svelte';
10
10
  import { refreshStateStore } from '../../../../svelte5Utils.svelte';
11
11
  import DiffDrawer from '../../../DiffDrawer.svelte';
12
- let { flowModuleSchemaMap } = $props();
12
+ let { flowModuleSchemaMap, } = $props();
13
13
  const { flowStore, flowStateStore, selectedId, currentEditor } = getContext('FlowEditorContext');
14
14
  const { exprsToSet } = getContext('FlowCopilotContext') ?? {};
15
15
  let affectedModules = $state({});
@@ -2,6 +2,7 @@ import { type FlowModule } from '../../../../gen';
2
2
  import type { ChatCompletionSystemMessageParam, ChatCompletionUserMessageParam } from 'openai/resources/chat/completions.mjs';
3
3
  import { z } from 'zod';
4
4
  import { type Tool } from '../shared';
5
+ import type { ContextElement } from '../context';
5
6
  import type { ExtendedOpenFlow } from '../../../flows/types';
6
7
  export type AIModuleAction = 'added' | 'modified' | 'removed';
7
8
  export interface FlowAIChatHelpers {
@@ -130,5 +131,5 @@ export declare function prepareFlowSystemMessage(): ChatCompletionSystemMessageP
130
131
  export declare function prepareFlowUserMessage(instructions: string, flowAndSelectedId?: {
131
132
  flow: ExtendedOpenFlow;
132
133
  selectedId: string;
133
- }): ChatCompletionUserMessageParam;
134
+ }, selectedContext?: ContextElement[]): ChatCompletionUserMessageParam;
134
135
  export {};
@@ -3,8 +3,8 @@ import YAML from 'yaml';
3
3
  import { z } from 'zod';
4
4
  import uFuzzy from '@leeoniya/ufuzzy';
5
5
  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';
6
+ import { getFormattedResourceTypes, getLangContext, SUPPORTED_CHAT_SCRIPT_LANGUAGES, createDbSchemaTool } from '../script/core';
7
+ import { createSearchHubScriptsTool, createToolDef, executeTestRun, buildSchemaForTool, buildTestRunArgs, buildContextString, applyCodePiecesToFlowModules, findModuleById } from '../shared';
8
8
  const searchScriptsSchema = z.object({
9
9
  query: z
10
10
  .string()
@@ -188,7 +188,10 @@ const getInstructionsForCodeGenerationToolSchema = z.object({
188
188
  const getInstructionsForCodeGenerationToolDef = createToolDef(getInstructionsForCodeGenerationToolSchema, 'get_instructions_for_code_generation', 'Get instructions for code generation for a raw script step');
189
189
  // Will be overridden by setSchema
190
190
  const testRunFlowSchema = z.object({
191
- args: z.object({}).nullable().optional()
191
+ args: z
192
+ .object({})
193
+ .nullable()
194
+ .optional()
192
195
  .describe('Arguments to pass to the flow (optional, uses default flow inputs if not provided)')
193
196
  });
194
197
  const testRunFlowToolDef = createToolDef(testRunFlowSchema, 'test_run_flow', 'Execute a test run of the current flow');
@@ -204,6 +207,7 @@ const testRunStepToolDef = createToolDef(testRunStepSchema, 'test_run_step', 'Ex
204
207
  const workspaceScriptsSearch = new WorkspaceScriptsSearch();
205
208
  export const flowTools = [
206
209
  createSearchHubScriptsTool(false),
210
+ createDbSchemaTool(),
207
211
  {
208
212
  def: searchScriptsToolDef,
209
213
  fn: async ({ args, workspace, toolId, toolCallbacks }) => {
@@ -405,7 +409,7 @@ export const flowTools = [
405
409
  workspace: workspace,
406
410
  requestBody: {
407
411
  args: parsedArgs,
408
- value: flow.value,
412
+ value: flow.value
409
413
  }
410
414
  }),
411
415
  workspace,
@@ -441,7 +445,7 @@ export const flowTools = [
441
445
  const stepArgs = args.args || {};
442
446
  // Find the step in the flow
443
447
  const modules = helpers.getModules();
444
- let targetModule = modules.find((m) => m.id === stepId);
448
+ let targetModule = findModuleById(modules, stepId);
445
449
  if (!targetModule) {
446
450
  toolCallbacks.setToolStatus(toolId, {
447
451
  content: `Step '${stepId}' not found in flow`,
@@ -459,7 +463,9 @@ export const flowTools = [
459
463
  requestBody: {
460
464
  content: moduleValue.content ?? '',
461
465
  language: moduleValue.language,
462
- args: module.id === 'preprocessor' ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs } : stepArgs
466
+ args: module.id === 'preprocessor'
467
+ ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs }
468
+ : stepArgs
463
469
  }
464
470
  }),
465
471
  workspace,
@@ -486,7 +492,9 @@ export const flowTools = [
486
492
  requestBody: {
487
493
  content: script.content,
488
494
  language: script.language,
489
- args: module.id === 'preprocessor' ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs } : stepArgs,
495
+ args: module.id === 'preprocessor'
496
+ ? { _ENTRYPOINT_OVERRIDE: 'preprocessor', ...stepArgs }
497
+ : stepArgs
490
498
  }
491
499
  }),
492
500
  workspace,
@@ -530,6 +538,16 @@ Follow the user instructions carefully.
530
538
  Go step by step, and explain what you're doing as you're doing it.
531
539
  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
540
  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.
541
+ When testing steps that are sql scripts, the arguments to be passed are { database: $res:<db_resource> }.
542
+
543
+ ## Code Markers in Flow Modules
544
+
545
+ When viewing flow modules, the code content of rawscript steps may include \`[#START]\` and \`[#END]\` markers:
546
+ - These markers indicate specific code sections that need attention
547
+ - You MUST only modify the code between these markers when using the \`set_code\` tool
548
+ - After modifying the code, remove the markers from your response
549
+ - If a question is asked about the code, focus only on the code between the markers
550
+ - The markers appear in the YAML representation of flow modules when specific code pieces are selected
533
551
 
534
552
  ## Understanding User Requests
535
553
 
@@ -611,6 +629,16 @@ For truly static values in step inputs (those not linked to previous steps or lo
611
629
 
612
630
  Both modules only support a script or rawscript step. You cannot nest modules using forloop/branchone/branchall.
613
631
 
632
+ ### Contexts
633
+
634
+ You have access to the following contexts:
635
+ - Database schemas
636
+ - Flow diffs
637
+ - Focused flow modules
638
+ Database schemas give you the schema of databases the user is using.
639
+ Flow diffs give you the diff between the current flow and the last deployed flow.
640
+ Focused flow modules give you the ids of the flow modules the user is focused on. Your response should focus on these modules.
641
+
614
642
  ## Resource types
615
643
  On Windmill, credentials and configuration are stored in resources. Resource types define the format of the resource.
616
644
  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 +649,27 @@ If the user wants a specific resource as step input, you should set the step val
621
649
  content
622
650
  };
623
651
  }
624
- export function prepareFlowUserMessage(instructions, flowAndSelectedId) {
652
+ export function prepareFlowUserMessage(instructions, flowAndSelectedId, selectedContext) {
625
653
  const flow = flowAndSelectedId?.flow;
626
654
  const selectedId = flowAndSelectedId?.selectedId;
655
+ // Handle context elements
656
+ const contextInstructions = selectedContext ? buildContextString(selectedContext) : '';
627
657
  if (!flow || !selectedId) {
658
+ let userMessage = `## INSTRUCTIONS:
659
+ ${instructions}`;
628
660
  return {
629
661
  role: 'user',
630
- content: `## INSTRUCTIONS:
631
- ${instructions}`
662
+ content: userMessage
632
663
  };
633
664
  }
634
- return {
635
- role: 'user',
636
- content: `## FLOW:
665
+ const codePieces = selectedContext?.filter((c) => c.type === 'code_piece') ?? [];
666
+ const flowModulesYaml = applyCodePiecesToFlowModules(codePieces, flow.value.modules);
667
+ let flowContent = `## FLOW:
637
668
  flow_input schema:
638
669
  ${JSON.stringify(flow.schema ?? emptySchema())}
639
670
 
640
671
  flow modules:
641
- ${YAML.stringify(flow.value.modules)}
672
+ ${flowModulesYaml}
642
673
 
643
674
  preprocessor module:
644
675
  ${YAML.stringify(flow.value.preprocessor_module)}
@@ -647,9 +678,12 @@ failure module:
647
678
  ${YAML.stringify(flow.value.failure_module)}
648
679
 
649
680
  currently selected step:
650
- ${selectedId}
651
-
652
- ## INSTRUCTIONS:
653
- ${instructions}`
681
+ ${selectedId}`;
682
+ flowContent += contextInstructions;
683
+ flowContent += `\n\n## INSTRUCTIONS:
684
+ ${instructions}`;
685
+ return {
686
+ role: 'user',
687
+ content: flowContent
654
688
  };
655
689
  }
@@ -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;