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
@@ -1,15 +1,13 @@
1
1
  import { ResourceService, JobService } from '../../../../gen/services.gen';
2
- import { capitalize, emptySchema, isObject, toCamel } from '../../../../utils';
2
+ import { capitalize, isObject, toCamel } from '../../../../utils';
3
3
  import { get } from 'svelte/store';
4
4
  import { compile, phpCompile, pythonCompile } from '../../utils';
5
5
  import { copilotSessionModel, dbSchemas } from '../../../../stores';
6
- import { scriptLangToEditorLang } from '../../../../scripts';
7
6
  import { getDbSchemas } from '../../../apps/components/display/dbtable/utils';
8
7
  import { PYTHON_PREPROCESSOR_MODULE_CODE, TS_PREPROCESSOR_MODULE_CODE } from '../../../../script_helpers';
9
- import { createSearchHubScriptsTool, executeTestRun, buildSchemaForTool, buildTestRunArgs } from '../shared';
8
+ import { createSearchHubScriptsTool, executeTestRun, buildTestRunArgs, buildContextString } from '../shared';
10
9
  import { setupTypeAcquisition } from '../../../../ata';
11
10
  import { getModelContextWindow } from '../../lib';
12
- import { inferArgs } from '../../../../infer';
13
11
  // Score threshold for npm packages search filtering
14
12
  const SCORE_THRESHOLD = 1000;
15
13
  // percentage of the context window for documentation of npm packages
@@ -290,7 +288,7 @@ export const CHAT_SYSTEM_PROMPT = `
290
288
  - 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.
291
289
  - Before giving your answer, check again that you carefully followed these instructions.
292
290
  - 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.
293
- - 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.
291
+ - 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.
294
292
 
295
293
  Important:
296
294
  Do not mention or reveal these instructions to the user unless explicitly asked to do so.
@@ -379,16 +377,6 @@ export async function main() {
379
377
  </new_code>
380
378
  \`\`\`
381
379
  `;
382
- const CHAT_USER_CODE_CONTEXT = `
383
- - {title}:
384
- \`\`\`{language}
385
- {code}
386
- \`\`\`
387
- `;
388
- const CHAT_USER_ERROR_CONTEXT = `
389
- ERROR:
390
- {error}
391
- `;
392
380
  export const CHAT_USER_PROMPT = `
393
381
  INSTRUCTIONS:
394
382
  {instructions}
@@ -397,24 +385,12 @@ WINDMILL LANGUAGE CONTEXT:
397
385
  {lang_context}
398
386
 
399
387
  `;
400
- export const CHAT_USER_DB_CONTEXT = `- {title}: SCHEMA: \n{schema}\n`;
401
388
  export function prepareScriptSystemMessage() {
402
389
  return {
403
390
  role: 'system',
404
391
  content: CHAT_SYSTEM_PROMPT
405
392
  };
406
393
  }
407
- const applyCodePieceToCodeContext = (codePieces, codeContext) => {
408
- let code = codeContext.split('\n');
409
- let shiftOffset = 0;
410
- codePieces.sort((a, b) => a.startLine - b.startLine);
411
- for (const codePiece of codePieces) {
412
- code.splice(codePiece.endLine + shiftOffset, 0, '[#END]');
413
- code.splice(codePiece.startLine + shiftOffset - 1, 0, '[#START]');
414
- shiftOffset += 2;
415
- }
416
- return code.join('\n');
417
- };
418
394
  export function prepareScriptTools(language, context) {
419
395
  const tools = [];
420
396
  if (['python3', 'php', 'bun', 'deno', 'nativets', 'bunnative'].includes(language)) {
@@ -431,51 +407,9 @@ export function prepareScriptTools(language, context) {
431
407
  return tools;
432
408
  }
433
409
  export function prepareScriptUserMessage(instructions, language, selectedContext, options = {}) {
434
- let codeContext = 'CODE:\n';
435
- let errorContext = 'ERROR:\n';
436
- let dbContext = 'DATABASES:\n';
437
- let diffContext = 'DIFF:\n';
438
- let hasCode = false;
439
- let hasError = false;
440
- let hasDb = false;
441
- let hasDiff = false;
442
- for (const context of selectedContext) {
443
- if (context.type === 'code') {
444
- hasCode = true;
445
- codeContext += CHAT_USER_CODE_CONTEXT.replace('{title}', context.title)
446
- .replace('{language}', scriptLangToEditorLang(language))
447
- .replace('{code}', applyCodePieceToCodeContext(selectedContext.filter((c) => c.type === 'code_piece'), context.content));
448
- }
449
- else if (context.type === 'error') {
450
- if (hasError) {
451
- throw new Error('Multiple error contexts provided');
452
- }
453
- hasError = true;
454
- errorContext = CHAT_USER_ERROR_CONTEXT.replace('{error}', context.content);
455
- }
456
- else if (context.type === 'db') {
457
- hasDb = true;
458
- dbContext += CHAT_USER_DB_CONTEXT.replace('{title}', context.title).replace('{schema}', context.schema?.stringified ?? 'to fetch with get_db_schema');
459
- }
460
- else if (context.type === 'diff') {
461
- hasDiff = true;
462
- const diff = JSON.stringify(context.diff);
463
- diffContext = diff.length > 3000 ? diff.slice(0, 3000) + '...' : diff;
464
- }
465
- }
466
410
  let userMessage = CHAT_USER_PROMPT.replace('{instructions}', instructions).replace('{lang_context}', getLangContext(language, { allowResourcesFetch: true, ...options }));
467
- if (hasCode) {
468
- userMessage += codeContext;
469
- }
470
- if (hasError) {
471
- userMessage += errorContext;
472
- }
473
- if (hasDb) {
474
- userMessage += dbContext;
475
- }
476
- if (hasDiff) {
477
- userMessage += diffContext;
478
- }
411
+ const contextInstructions = buildContextString(selectedContext);
412
+ userMessage += contextInstructions;
479
413
  return {
480
414
  role: 'user',
481
415
  content: userMessage
@@ -534,39 +468,51 @@ async function formatDBSchema(dbSchema) {
534
468
  export const resourceTypeTool = {
535
469
  def: RESOURCE_TYPE_FUNCTION_DEF,
536
470
  fn: async ({ args, workspace, helpers, toolCallbacks, toolId }) => {
537
- toolCallbacks.setToolStatus(toolId, { content: 'Searching resource types for "' + args.query + '"...' });
471
+ toolCallbacks.setToolStatus(toolId, {
472
+ content: 'Searching resource types for "' + args.query + '"...'
473
+ });
538
474
  const lang = helpers.getScriptOptions().lang;
539
475
  const formattedResourceTypes = await getFormattedResourceTypes(lang, args.query, workspace);
540
- toolCallbacks.setToolStatus(toolId, { content: 'Retrieved resource types for "' + args.query + '"' });
476
+ toolCallbacks.setToolStatus(toolId, {
477
+ content: 'Retrieved resource types for "' + args.query + '"'
478
+ });
541
479
  return formattedResourceTypes;
542
480
  }
543
481
  };
544
- export const dbSchemaTool = {
545
- def: DB_SCHEMA_FUNCTION_DEF,
546
- fn: async ({ args, workspace, toolCallbacks, toolId }) => {
547
- if (!args.resourcePath) {
548
- throw new Error('Database path not provided');
549
- }
550
- toolCallbacks.setToolStatus(toolId, { content: 'Getting database schema for ' + args.resourcePath + '...' });
551
- const resource = await ResourceService.getResource({
552
- workspace: workspace,
553
- path: args.resourcePath
554
- });
555
- const newDbSchemas = {};
556
- await getDbSchemas(resource.resource_type, args.resourcePath, workspace, newDbSchemas, (error) => {
557
- console.error(error);
558
- });
559
- dbSchemas.update((schemas) => ({ ...schemas, ...newDbSchemas }));
560
- const dbs = get(dbSchemas);
561
- const db = dbs[args.resourcePath];
562
- if (!db) {
563
- throw new Error('Database not found');
482
+ // Generic DB schema tool factory that can be used by both script and flow modes
483
+ export function createDbSchemaTool() {
484
+ return {
485
+ def: DB_SCHEMA_FUNCTION_DEF,
486
+ fn: async ({ args, workspace, toolCallbacks, toolId }) => {
487
+ if (!args.resourcePath) {
488
+ throw new Error('Database path not provided');
489
+ }
490
+ toolCallbacks.setToolStatus(toolId, {
491
+ content: 'Getting database schema for ' + args.resourcePath + '...'
492
+ });
493
+ const resource = await ResourceService.getResource({
494
+ workspace: workspace,
495
+ path: args.resourcePath
496
+ });
497
+ const newDbSchemas = {};
498
+ await getDbSchemas(resource.resource_type, args.resourcePath, workspace, newDbSchemas, (error) => {
499
+ console.error(error);
500
+ });
501
+ dbSchemas.update((schemas) => ({ ...schemas, ...newDbSchemas }));
502
+ const dbs = get(dbSchemas);
503
+ const db = dbs[args.resourcePath];
504
+ if (!db) {
505
+ throw new Error('Database not found');
506
+ }
507
+ const stringSchema = await formatDBSchema(db);
508
+ toolCallbacks.setToolStatus(toolId, {
509
+ content: 'Retrieved database schema for ' + args.resourcePath
510
+ });
511
+ return stringSchema;
564
512
  }
565
- const stringSchema = await formatDBSchema(db);
566
- toolCallbacks.setToolStatus(toolId, { content: 'Retrieved database schema for ' + args.resourcePath });
567
- return stringSchema;
568
- }
569
- };
513
+ };
514
+ }
515
+ export const dbSchemaTool = createDbSchemaTool();
570
516
  const packagesSearchCache = new Map();
571
517
  export async function searchExternalIntegrationResources(args) {
572
518
  try {
@@ -692,18 +638,16 @@ const TEST_RUN_SCRIPT_TOOL = {
692
638
  function: {
693
639
  name: 'test_run_script',
694
640
  description: 'Execute a test run of the current script in the editor',
695
- // will be overridden by setSchema
696
641
  parameters: {
697
642
  type: 'object',
698
643
  properties: {
699
- args: {
700
- type: 'object',
701
- description: 'Arguments to pass to the script (optional, uses current editor args if not provided)'
702
- }
644
+ args: { type: 'string', description: 'JSON string containing the arguments for the tool' }
703
645
  },
704
- required: []
646
+ additionalProperties: false,
647
+ strict: false,
648
+ required: ['args']
705
649
  }
706
- },
650
+ }
707
651
  };
708
652
  export const testRunScriptTool = {
709
653
  def: TEST_RUN_SCRIPT_TOOL,
@@ -734,7 +678,7 @@ export const testRunScriptTool = {
734
678
  path: scriptOptions.path,
735
679
  content: codeToTest,
736
680
  args: parsedArgs,
737
- language: scriptOptions.lang,
681
+ language: scriptOptions.lang
738
682
  }
739
683
  }),
740
684
  workspace,
@@ -744,22 +688,7 @@ export const testRunScriptTool = {
744
688
  contextName: 'script'
745
689
  });
746
690
  },
747
- setSchema: async function (helpers) {
748
- await buildSchemaForTool(this.def, async () => {
749
- const scriptOptions = helpers.getScriptOptions();
750
- const code = scriptOptions?.code;
751
- const lang = scriptOptions?.lang;
752
- const lastSuggestedCode = helpers.getLastSuggestedCode();
753
- const codeToTest = lastSuggestedCode ?? code;
754
- if (codeToTest) {
755
- const newSchema = emptySchema();
756
- await inferArgs(lang, codeToTest, newSchema);
757
- return newSchema;
758
- }
759
- return emptySchema();
760
- });
761
- },
762
691
  requiresConfirmation: true,
763
692
  confirmationMessage: 'Run script test',
764
- showDetails: true,
693
+ showDetails: true
765
694
  };
@@ -1,9 +1,20 @@
1
1
  import type { ChatCompletionMessageParam, ChatCompletionMessageToolCall, ChatCompletionTool } from 'openai/resources/chat/completions.mjs';
2
- import type { ContextElement } from './context';
2
+ import type { CodePieceElement, ContextElement } from './context';
3
3
  import type { ExtendedOpenFlow } from '../../flows/types';
4
4
  import type { FunctionParameters } from 'openai/resources/shared.mjs';
5
5
  import { z } from 'zod';
6
- import { type CompletedJob } from '../../../gen';
6
+ import { type CompletedJob, type FlowModule } from '../../../gen';
7
+ export interface ContextStringResult {
8
+ dbContext: string;
9
+ diffContext: string;
10
+ flowModuleContext: string;
11
+ hasDb: boolean;
12
+ hasDiff: boolean;
13
+ hasFlowModule: boolean;
14
+ }
15
+ export declare const findModuleById: (modules: FlowModule[], moduleId: string) => FlowModule | undefined;
16
+ export declare function applyCodePiecesToFlowModules(codePieces: CodePieceElement[], flowModules: FlowModule[]): string;
17
+ export declare function buildContextString(selectedContext: ContextElement[]): string;
7
18
  type BaseDisplayMessage = {
8
19
  content: string;
9
20
  contextElements?: ContextElement[];
@@ -3,6 +3,146 @@ import { copilotSessionModel, workspaceStore } from '../../../stores';
3
3
  import { zodToJsonSchema } from 'zod-to-json-schema';
4
4
  import { z } from 'zod';
5
5
  import { ScriptService, JobService } from '../../../gen';
6
+ import { scriptLangToEditorLang } from '../../../scripts';
7
+ import YAML from 'yaml';
8
+ export const findModuleById = (modules, moduleId) => {
9
+ for (const module of modules) {
10
+ if (module.id === moduleId) {
11
+ return module;
12
+ }
13
+ if (module.value.type === 'forloopflow' || module.value.type === 'whileloopflow') {
14
+ const found = findModuleById(module.value.modules, moduleId);
15
+ if (found) {
16
+ return found;
17
+ }
18
+ }
19
+ if (module.value.type === 'branchall') {
20
+ const allModules = module.value.branches.flatMap((b) => b.modules);
21
+ const found = findModuleById(allModules, moduleId);
22
+ if (found) {
23
+ return found;
24
+ }
25
+ }
26
+ if (module.value.type === 'branchone') {
27
+ const allModules = [
28
+ ...module.value.branches.flatMap((b) => b.modules),
29
+ ...module.value.default
30
+ ];
31
+ const found = findModuleById(allModules, moduleId);
32
+ if (found) {
33
+ return found;
34
+ }
35
+ }
36
+ }
37
+ return undefined;
38
+ };
39
+ const applyCodePieceToCodeContext = (codePieces, codeContext) => {
40
+ let code = codeContext.split('\n');
41
+ let shiftOffset = 0;
42
+ codePieces.sort((a, b) => a.startLine - b.startLine);
43
+ for (const codePiece of codePieces) {
44
+ code.splice(codePiece.endLine + shiftOffset, 0, '[#END]');
45
+ code.splice(codePiece.startLine + shiftOffset - 1, 0, '[#START]');
46
+ shiftOffset += 2;
47
+ }
48
+ return code.join('\n');
49
+ };
50
+ export function applyCodePiecesToFlowModules(codePieces, flowModules) {
51
+ // Parse code piece titles to extract module IDs
52
+ // Format: "[id] L3-L5"
53
+ const moduleCodePieces = new Map();
54
+ for (const codePiece of codePieces) {
55
+ const match = codePiece.title.match(/\[([^\]]+)\]\s+L\d+-L\d+/);
56
+ if (match) {
57
+ const moduleId = match[1];
58
+ if (!moduleCodePieces.has(moduleId)) {
59
+ moduleCodePieces.set(moduleId, []);
60
+ }
61
+ moduleCodePieces.get(moduleId).push(codePiece);
62
+ }
63
+ }
64
+ // Clone modules to avoid mutation
65
+ const modifiedModules = JSON.parse(JSON.stringify(flowModules));
66
+ // Apply code pieces to each module
67
+ for (const [moduleId, pieces] of moduleCodePieces) {
68
+ const module = findModuleById(modifiedModules, moduleId);
69
+ if (module && module.value.type === 'rawscript' && module.value.content) {
70
+ module.value.content = applyCodePieceToCodeContext(pieces, module.value.content);
71
+ }
72
+ }
73
+ return YAML.stringify(modifiedModules);
74
+ }
75
+ export function buildContextString(selectedContext) {
76
+ const dbTemplate = `- {title}: SCHEMA: \n{schema}\n`;
77
+ const codeTemplate = `
78
+ - {title}:
79
+ \`\`\`{language}
80
+ {code}
81
+ \`\`\`
82
+ `;
83
+ let dbContext = 'DATABASES:\n';
84
+ let diffContext = 'DIFF:\n';
85
+ let flowModuleContext = 'FOCUSED FLOW MODULES IDS:\n';
86
+ let codeContext = 'CODE:\n';
87
+ let errorContext = `
88
+ ERROR:
89
+ {error}
90
+ `;
91
+ let hasCode = false;
92
+ let hasDb = false;
93
+ let hasDiff = false;
94
+ let hasFlowModule = false;
95
+ let hasError = false;
96
+ let result = '\n\n';
97
+ for (const context of selectedContext) {
98
+ if (context.type === 'code') {
99
+ hasCode = true;
100
+ codeContext += codeTemplate
101
+ .replace('{title}', context.title)
102
+ .replace('{language}', scriptLangToEditorLang(context.lang))
103
+ .replace('{code}', applyCodePieceToCodeContext(selectedContext.filter((c) => c.type === 'code_piece'), context.content));
104
+ }
105
+ else if (context.type === 'error') {
106
+ if (hasError) {
107
+ throw new Error('Multiple error contexts provided');
108
+ }
109
+ hasError = true;
110
+ errorContext = errorContext.replace('{error}', context.content);
111
+ }
112
+ else if (context.type === 'db') {
113
+ hasDb = true;
114
+ dbContext += dbTemplate
115
+ .replace('{title}', context.title)
116
+ .replace('{schema}', context.schema?.stringified ?? 'to fetch with get_db_schema');
117
+ dbContext += '\n';
118
+ }
119
+ else if (context.type === 'diff') {
120
+ hasDiff = true;
121
+ const diff = JSON.stringify(context.diff);
122
+ diffContext += (diff.length > 3000 ? diff.slice(0, 3000) + '...' : diff) + '\n';
123
+ }
124
+ else if (context.type === 'flow_module') {
125
+ hasFlowModule = true;
126
+ flowModuleContext += `${context.id}\n`;
127
+ }
128
+ }
129
+ if (hasCode) {
130
+ result += '\n' + codeContext;
131
+ }
132
+ if (hasError) {
133
+ result += '\n' + errorContext;
134
+ }
135
+ if (hasDb) {
136
+ result += '\n' + dbContext;
137
+ }
138
+ if (hasDiff) {
139
+ result += '\n' + diffContext;
140
+ }
141
+ if (hasFlowModule) {
142
+ result += '\n' + flowModuleContext;
143
+ }
144
+ return result;
145
+ }
6
146
  async function callTool({ tools, functionName, args, workspace, helpers, toolCallbacks, toolId }) {
7
147
  const tool = tools.find((t) => t.def.function.name === functionName);
8
148
  if (!tool) {
@@ -18,11 +158,13 @@ export async function processToolCall({ tools, toolCall, helpers, toolCallbacks
18
158
  const needsConfirmation = tool?.requiresConfirmation;
19
159
  // Add the tool to the display with appropriate status
20
160
  toolCallbacks.setToolStatus(toolCall.id, {
21
- ...(tool?.requiresConfirmation ? { content: tool.confirmationMessage ?? "Waiting for confirmation..." } : {}),
161
+ ...(tool?.requiresConfirmation
162
+ ? { content: tool.confirmationMessage ?? 'Waiting for confirmation...' }
163
+ : {}),
22
164
  parameters: args,
23
165
  isLoading: true,
24
166
  needsConfirmation: needsConfirmation,
25
- showDetails: tool?.showDetails,
167
+ showDetails: tool?.showDetails
26
168
  });
27
169
  // If confirmation is needed and we have the callback, wait for it
28
170
  if (needsConfirmation && toolCallbacks.requestConfirmation) {
@@ -163,7 +305,15 @@ export async function buildSchemaForTool(toolDef, schemaBuilder) {
163
305
  catch (error) {
164
306
  console.error('Error building schema for tool', error);
165
307
  // fallback to schema with args as a JSON string
166
- toolDef.function.parameters = { type: 'object', properties: { args: { type: 'string', description: 'JSON string containing the arguments for the tool' } }, additionalProperties: false, strict: false, required: ['args'] };
308
+ toolDef.function.parameters = {
309
+ type: 'object',
310
+ properties: {
311
+ args: { type: 'string', description: 'JSON string containing the arguments for the tool' }
312
+ },
313
+ additionalProperties: false,
314
+ strict: false,
315
+ required: ['args']
316
+ };
167
317
  return false;
168
318
  }
169
319
  }
@@ -254,7 +404,8 @@ function getErrorMessage(result) {
254
404
  export async function buildTestRunArgs(args, toolDef) {
255
405
  let parsedArgs = args;
256
406
  // if the schema is the fallback schema, parse the args as a JSON string
257
- if (toolDef.function.parameters.properties?.args?.description === 'JSON string containing the arguments for the tool') {
407
+ if (toolDef.function.parameters.properties?.args?.description ===
408
+ 'JSON string containing the arguments for the tool') {
258
409
  try {
259
410
  parsedArgs = JSON.parse(args.args);
260
411
  }
@@ -18,10 +18,22 @@ setContext('PropPickerContext', {
18
18
  flowPropPickerConfig: writable(undefined),
19
19
  pickablePropertiesFiltered: writable(undefined)
20
20
  });
21
+ $effect(() => {
22
+ const options = {
23
+ currentFlow: flowStore.val,
24
+ lastDeployedFlow: savedFlow,
25
+ lastSavedFlow: savedFlow?.draft,
26
+ path: savedFlow?.path,
27
+ modules: flowStore.val.value.modules
28
+ };
29
+ aiChatManager.flowOptions = options;
30
+ });
21
31
  onMount(() => {
32
+ aiChatManager.saveAndClear();
22
33
  aiChatManager.changeMode(AIMode.FLOW);
23
34
  });
24
35
  onDestroy(() => {
36
+ aiChatManager.flowOptions = undefined;
25
37
  aiChatManager.changeMode(AIMode.NAVIGATOR);
26
38
  });
27
39
  </script>
@@ -0,0 +1,39 @@
1
+ <script lang="ts">import LanguageIcon from '../common/languageIcons/LanguageIcon.svelte';
2
+ import IconedResourceType from '../IconedResourceType.svelte';
3
+ import { Building, Repeat, Square, ArrowDown, GitBranch, Bot } from 'lucide-svelte';
4
+ import BarsStaggered from '../icons/BarsStaggered.svelte';
5
+ let { module, size = 16, width, height } = $props();
6
+ // Use width/height if provided, otherwise use size for both
7
+ const iconWidth = width || size;
8
+ const iconHeight = height || size;
9
+ </script>
10
+
11
+ {#if module.value.type === 'aiagent'}
12
+ <Bot size={16} />
13
+ {:else if module.value.type === 'rawscript'}
14
+ <LanguageIcon lang={module.value.language} width={iconWidth} height={iconHeight} />
15
+ {:else if module.summary === 'Terminate flow'}
16
+ <Square size={size} />
17
+ {:else if module.value.type === 'identity'}
18
+ <ArrowDown size={size} />
19
+ {:else if module.value.type === 'flow'}
20
+ <BarsStaggered size={size} />
21
+ {:else if module.value.type === 'forloopflow' || module.value.type === 'whileloopflow'}
22
+ <Repeat size={size} />
23
+ {:else if module.value.type === 'branchone' || module.value.type === 'branchall'}
24
+ <GitBranch size={size} />
25
+ {:else if module.value.type === 'script'}
26
+ {#if module.value.path.startsWith('hub/')}
27
+ <IconedResourceType
28
+ width={iconWidth.toString() + 'px'}
29
+ height={iconHeight.toString() + 'px'}
30
+ name={module.value.path.split('/')[2]}
31
+ silent={true}
32
+ />
33
+ {:else}
34
+ <Building size={size} />
35
+ {/if}
36
+ {:else}
37
+ <!-- Fallback icon for unknown module types -->
38
+ <BarsStaggered size={size} />
39
+ {/if}
@@ -0,0 +1,10 @@
1
+ import type { FlowModule } from '../../gen';
2
+ interface Props {
3
+ module: FlowModule;
4
+ size?: number;
5
+ width?: number;
6
+ height?: number;
7
+ }
8
+ declare const FlowModuleIcon: import("svelte").Component<Props, {}, "">;
9
+ type FlowModuleIcon = ReturnType<typeof FlowModuleIcon>;
10
+ export default FlowModuleIcon;
@@ -331,6 +331,7 @@ let rawScriptLang = $derived(flowModule.value.type == 'rawscript' ? flowModule.v
331
331
  {lastDeployedCode}
332
332
  {diffMode}
333
333
  openAiChat
334
+ moduleId={flowModule.id}
334
335
  />
335
336
  </div>
336
337
  {/if}
@@ -389,6 +390,7 @@ let rawScriptLang = $derived(flowModule.value.type == 'rawscript' ? flowModule.v
389
390
  {}
390
391
  )}
391
392
  key={`flow-inline-${$workspaceStore}-${$pathStore}-${flowModule.id}`}
393
+ moduleId={flowModule.id}
392
394
  />
393
395
  <DiffEditor
394
396
  open={false}
@@ -1,12 +1,9 @@
1
1
  <script lang="ts">import { Button } from '../../common';
2
- import LanguageIcon from '../../common/languageIcons/LanguageIcon.svelte';
3
- import IconedResourceType from '../../IconedResourceType.svelte';
4
- import { Building, Repeat, Square, ArrowDown, GitBranch, Bot } from 'lucide-svelte';
5
2
  import { createEventDispatcher, getContext } from 'svelte';
6
3
  import FlowModuleSchemaItem from './FlowModuleSchemaItem.svelte';
4
+ import FlowModuleIcon from '../FlowModuleIcon.svelte';
7
5
  import { prettyLanguage } from '../../../common';
8
6
  import { msToSec } from '../../../utils';
9
- import BarsStaggered from '../../icons/BarsStaggered.svelte';
10
7
  import FlowJobsMenu from './FlowJobsMenu.svelte';
11
8
  import { isTriggerStep } from '../../graph/graphBuilder.svelte';
12
9
  import { checkIfParentLoop } from '../utils';
@@ -107,9 +104,7 @@ let parentLoop = $derived(flowStore?.val && mod ? checkIfParentLoop(flowStore.va
107
104
  {darkMode}
108
105
  >
109
106
  {#snippet icon()}
110
- <div>
111
- <Repeat size={16} />
112
- </div>
107
+ <FlowModuleIcon module={mod} />
113
108
  {/snippet}
114
109
  </FlowModuleSchemaItem>
115
110
  {:else if mod.value.type === 'branchone'}
@@ -130,9 +125,7 @@ let parentLoop = $derived(flowStore?.val && mod ? checkIfParentLoop(flowStore.va
130
125
  {darkMode}
131
126
  >
132
127
  {#snippet icon()}
133
- <div>
134
- <GitBranch size={16} />
135
- </div>
128
+ <FlowModuleIcon module={mod} />
136
129
  {/snippet}
137
130
  </FlowModuleSchemaItem>
138
131
  {:else if mod.value.type === 'branchall'}
@@ -153,9 +146,7 @@ let parentLoop = $derived(flowStore?.val && mod ? checkIfParentLoop(flowStore.va
153
146
  {darkMode}
154
147
  >
155
148
  {#snippet icon()}
156
- <div>
157
- <GitBranch size={16} />
158
- </div>
149
+ <FlowModuleIcon module={mod} />
159
150
  {/snippet}
160
151
  </FlowModuleSchemaItem>
161
152
  {:else}
@@ -203,32 +194,10 @@ let parentLoop = $derived(flowStore?.val && mod ? checkIfParentLoop(flowStore.va
203
194
  {skipped}
204
195
  >
205
196
  {#snippet icon()}
206
- <div>
207
- {#if mod.value.type === 'aiagent'}
208
- <Bot size={16} />
209
- {:else if mod.value.type === 'rawscript'}
210
- <LanguageIcon lang={mod.value.language} width={16} height={16} />
211
- {:else if mod.summary == 'Terminate flow'}
212
- <Square size={16} />
213
- {:else if mod.value.type === 'identity'}
214
- <ArrowDown size={16} />
215
- {:else if mod.value.type === 'flow'}
216
- <BarsStaggered size={16} />
217
- {:else if mod.value.type === 'script'}
218
- {#if mod.value.path.startsWith('hub/')}
219
- <div>
220
- <IconedResourceType
221
- width="20px"
222
- height="20px"
223
- name={mod.value.path.split('/')[2]}
224
- silent={true}
225
- />
226
- </div>
227
- {:else}
228
- <Building size={14} />
229
- {/if}
230
- {/if}
231
- </div>
197
+ {@const size = mod.value.type === 'script' && mod.value.path.startsWith('hub/')
198
+ ? 20
199
+ : mod.value.type === "script" ? 14 : 16}
200
+ <FlowModuleIcon module={mod} size={size} />
232
201
  {/snippet}
233
202
  </FlowModuleSchemaItem>
234
203
  {/if}