From 667704820d12f3915d7ca5171a8ad9d49827ef71 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Sat, 1 Feb 2025 17:37:04 -0800 Subject: [PATCH] Modified envvar detection & evaluation criteria to be text inside of {{}} instead of {} --- components/ui/formatted-text.tsx | 20 +++--- executor/__tests__/executor.test.ts | 104 ++++++++++++++++++++++++++++ executor/index.ts | 8 +-- 3 files changed, 119 insertions(+), 13 deletions(-) diff --git a/components/ui/formatted-text.tsx b/components/ui/formatted-text.tsx index cad4b14d3b..6c5f7fb79c 100644 --- a/components/ui/formatted-text.tsx +++ b/components/ui/formatted-text.tsx @@ -3,32 +3,34 @@ import { ReactNode } from 'react' /** - * Formats text by highlighting block references (<...>) and environment variables ({...}) + * Formats text by highlighting block references (<...>) and environment variables ({{...}}) * Used in code editor, long inputs, and short inputs for consistent syntax highlighting */ -export function formatDisplayText(text: string | null): ReactNode { - if (!text) return null +export function formatDisplayText(text: string): ReactNode[] { + if (!text) return [] - // Split the text by both tag patterns and {ENV_VAR} - const parts = text.split(/(<[^>]+>|\{[^}]+\})/g) + // Split the text by both tag patterns and {{ENV_VAR}} + const parts = text.split(/(<[^>]+>|\{\{[^}]+\}\})/g) return parts.map((part, index) => { - // Check if the part matches connection tag pattern - if (part.match(/^<[^>]+>$/)) { + // Handle block references + if (part.startsWith('<') && part.endsWith('>')) { return ( {part} ) } - // Check if the part matches environment variable pattern - if (part.match(/^\{[^}]+\}$/)) { + + // Handle environment variables + if (part.match(/^\{\{[^}]+\}\}$/)) { return ( {part} ) } + return {part} }) } \ No newline at end of file diff --git a/executor/__tests__/executor.test.ts b/executor/__tests__/executor.test.ts index 6480a72ba6..dcc95b688b 100644 --- a/executor/__tests__/executor.test.ts +++ b/executor/__tests__/executor.test.ts @@ -898,4 +898,108 @@ describe('Executor', () => { expect(fetchCalls).toHaveLength(2); }); }); + + describe('Environment Variables', () => { + beforeEach(() => { + // Reset fetch mock before each test + global.fetch = jest.fn() + }) + + it('should resolve environment variables with double curly braces', async () => { + const mockTool = createMockTool( + 'test-tool', + 'Test Tool', + { result: 'test processed', data: { status: 200 } } + ); + (tools as any)['test-tool'] = mockTool + + const workflow: SerializedWorkflow = { + version: '1.0', + blocks: [{ + id: 'block-1', + position: { x: 0, y: 0 }, + config: { + tool: 'test-tool', + params: { input: 'test {{ENV_VAR}}' } + }, + inputs: { input: 'string' }, + outputs: { + output: { + response: { + text: 'string', + status: 'number' + } as ValueType + } as BlockOutput + }, + enabled: true + }], + connections: [] + } + + // Mock fetch response + global.fetch = jest.fn().mockImplementation(() => + Promise.resolve({ + ok: true, + json: () => Promise.resolve({ + success: true, + output: { + text: 'test processed', + status: 200 + } + }) + }) + ) + + const envVars = { ENV_VAR: 'value' } + const executor = new Executor(workflow, {}, envVars) + const result = await executor.execute('workflow-1') + + expect(result.success).toBe(true) + expect(global.fetch).toHaveBeenCalledWith( + 'https://api.test.com/endpoint', + expect.objectContaining({ + method: 'POST', + body: JSON.stringify({ input: 'test value' }) + }) + ) + }) + + it('should throw error for undefined environment variables', async () => { + const mockTool = createMockTool( + 'test-tool', + 'Test Tool', + { result: 'test processed', data: { status: 200 } } + ); + (tools as any)['test-tool'] = mockTool + + const workflow: SerializedWorkflow = { + version: '1.0', + blocks: [{ + id: 'block-1', + position: { x: 0, y: 0 }, + config: { + tool: 'test-tool', + params: { input: 'test {{UNDEFINED_VAR}}' } + }, + inputs: { input: 'string' }, + outputs: { + output: { + response: { + text: 'string', + status: 'number' + } as ValueType + } as BlockOutput + }, + enabled: true + }], + connections: [] + } + + const executor = new Executor(workflow) + const result = await executor.execute('workflow-1') + + expect(result.success).toBe(false) + expect(result.error).toContain('Environment variable "UNDEFINED_VAR" was not found') + }) + }) }) diff --git a/executor/index.ts b/executor/index.ts index 6274895026..3bec42bab9 100644 --- a/executor/index.ts +++ b/executor/index.ts @@ -371,12 +371,12 @@ export class Executor { } } - // Handle environment variables with {} syntax - const envMatches = resolvedValue.match(/\{([^}]+)\}/g) + // Handle environment variables with {{}} syntax + const envMatches = resolvedValue.match(/\{\{([^}]+)\}\}/g) if (envMatches) { for (const match of envMatches) { - const envKey = match.slice(1, -1) // remove { and } - const envValue = context.environmentVariables?.[envKey] + const envKey = match.slice(2, -2) // remove {{ and }} + const envValue = this.environmentVariables?.[envKey] if (envValue === undefined) { throw new Error(`Environment variable "${envKey}" was not found.`)