diff --git a/packages/components/nodes/agentflow/ExecuteFlow/ExecuteFlow.ts b/packages/components/nodes/agentflow/ExecuteFlow/ExecuteFlow.ts index 195be510..06bc6746 100644 --- a/packages/components/nodes/agentflow/ExecuteFlow/ExecuteFlow.ts +++ b/packages/components/nodes/agentflow/ExecuteFlow/ExecuteFlow.ts @@ -9,6 +9,7 @@ import { } from '../../../src/Interface' import axios, { AxiosRequestConfig } from 'axios' import { getCredentialData, getCredentialParam, processTemplateVariables } from '../../../src/utils' +import JSON5 from 'json5' import { DataSource } from 'typeorm' import { BaseMessageLike } from '@langchain/core/messages' import { updateFlowState } from '../utils' @@ -167,9 +168,7 @@ class ExecuteFlow_Agentflow implements INode { let overrideConfig = nodeData.inputs?.executeFlowOverrideConfig if (typeof overrideConfig === 'string' && overrideConfig.startsWith('{') && overrideConfig.endsWith('}')) { try { - // Handle escaped square brackets and other common escape sequences - const unescapedConfig = overrideConfig.replace(/\\(\[|\])/g, '$1') - overrideConfig = JSON.parse(unescapedConfig) + overrideConfig = JSON5.parse(overrideConfig) } catch (parseError) { throw new Error(`Invalid JSON in executeFlowOverrideConfig: ${parseError.message}`) } diff --git a/packages/components/nodes/agentflow/HTTP/HTTP.ts b/packages/components/nodes/agentflow/HTTP/HTTP.ts index f7635ce0..405881a4 100644 --- a/packages/components/nodes/agentflow/HTTP/HTTP.ts +++ b/packages/components/nodes/agentflow/HTTP/HTTP.ts @@ -4,6 +4,7 @@ import FormData from 'form-data' import * as querystring from 'querystring' import { getCredentialData, getCredentialParam } from '../../../src/utils' import { secureAxiosRequest } from '../../../src/httpSecurity' +import JSON5 from 'json5' class HTTP_Agentflow implements INode { label: string @@ -19,34 +20,13 @@ class HTTP_Agentflow implements INode { credential: INodeParams inputs: INodeParams[] - private sanitizeJsonString(jsonString: string): string { - // Remove common problematic escape sequences that are not valid JSON - let sanitized = jsonString - // Remove escaped square brackets (not valid JSON) - .replace(/\\(\[|\])/g, '$1') - // Fix unquoted string values in JSON (simple case) - .replace(/:\s*([a-zA-Z][a-zA-Z0-9]*)\s*([,}])/g, ': "$1"$2') - // Fix trailing commas - .replace(/,(\s*[}\]])/g, '$1') - - return sanitized - } - private parseJsonBody(body: string): any { try { - // First try to parse as-is - return JSON.parse(body) + return JSON5.parse(body) } catch (error) { - try { - // If that fails, try to sanitize and parse - const sanitized = this.sanitizeJsonString(body) - return JSON.parse(sanitized) - } catch (sanitizeError) { - // If sanitization also fails, throw the original error with helpful message - throw new Error( - `Invalid JSON format in body. Original error: ${error.message}. Please ensure your JSON is properly formatted with quoted strings and valid escape sequences.` - ) - } + throw new Error( + `Invalid JSON format in body. Original error: ${error.message}. Please ensure your JSON is properly formatted with quoted strings and valid escape sequences.` + ) } } diff --git a/packages/components/nodes/agentflow/Iteration/Iteration.ts b/packages/components/nodes/agentflow/Iteration/Iteration.ts index 53026bb5..04dfbb51 100644 --- a/packages/components/nodes/agentflow/Iteration/Iteration.ts +++ b/packages/components/nodes/agentflow/Iteration/Iteration.ts @@ -1,4 +1,5 @@ import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface' +import JSON5 from 'json5' class Iteration_Agentflow implements INode { label: string @@ -41,10 +42,10 @@ class Iteration_Agentflow implements INode { // Helper function to clean JSON strings with redundant backslashes const safeParseJson = (str: string): string => { try { - return JSON.parse(str) + return JSON5.parse(str) } catch { // Try parsing after cleaning - return JSON.parse(str.replace(/\\(["'[\]{}])/g, '$1')) + return JSON5.parse(str.replace(/\\(["'[\]{}])/g, '$1')) } } diff --git a/packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts b/packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts index 3fa177bf..8592692a 100644 --- a/packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts +++ b/packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts @@ -4,6 +4,7 @@ import { MCPToolkit } from '../core' import { getVars, prepareSandboxVars } from '../../../../src/utils' import { DataSource } from 'typeorm' import hash from 'object-hash' +import JSON5 from 'json5' const mcpServerConfig = `{ "command": "npx", @@ -261,7 +262,7 @@ function substituteVariablesInString(str: string, sandbox: any): string { function convertToValidJSONString(inputString: string) { try { - const jsObject = Function('return ' + inputString)() + const jsObject = JSON5.parse(inputString) return JSON.stringify(jsObject, null, 2) } catch (error) { console.error('Error converting to JSON:', error) diff --git a/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts b/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts index 50c640c3..e66d40b5 100644 --- a/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts +++ b/packages/components/nodes/tools/RequestsDelete/RequestsDelete.ts @@ -1,6 +1,7 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' import { desc, RequestParameters, RequestsDeleteTool } from './core' +import JSON5 from 'json5' const codeExample = `{ "id": { @@ -130,7 +131,7 @@ class RequestsDelete_Tools implements INode { if (queryParamsSchema) obj.queryParamsSchema = queryParamsSchema if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) if (headers) { - const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) + const parsedHeaders = typeof headers === 'object' ? headers : JSON5.parse(stripHTMLFromToolInput(headers)) obj.headers = parsedHeaders } diff --git a/packages/components/nodes/tools/RequestsDelete/core.ts b/packages/components/nodes/tools/RequestsDelete/core.ts index a60dee95..1c71911d 100644 --- a/packages/components/nodes/tools/RequestsDelete/core.ts +++ b/packages/components/nodes/tools/RequestsDelete/core.ts @@ -1,6 +1,7 @@ import { z } from 'zod' import { DynamicStructuredTool } from '../OpenAPIToolkit/core' import { secureFetch } from '../../../src/httpSecurity' +import JSON5 from 'json5' export const desc = `Use this when you need to execute a DELETE request to remove data from a website.` @@ -22,7 +23,7 @@ const createRequestsDeleteSchema = (queryParamsSchema?: string) => { // If queryParamsSchema is provided, parse it and add dynamic query params if (queryParamsSchema) { try { - const parsedSchema = JSON.parse(queryParamsSchema) + const parsedSchema = JSON5.parse(queryParamsSchema) const queryParamsObject: Record = {} Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { @@ -108,7 +109,7 @@ export class RequestsDeleteTool extends DynamicStructuredTool { if (this.queryParamsSchema && params.queryParams && Object.keys(params.queryParams).length > 0) { try { - const parsedSchema = JSON.parse(this.queryParamsSchema) + const parsedSchema = JSON5.parse(this.queryParamsSchema) const pathParams: Array<{ key: string; value: string }> = [] Object.entries(params.queryParams).forEach(([key, value]) => { diff --git a/packages/components/nodes/tools/RequestsGet/RequestsGet.ts b/packages/components/nodes/tools/RequestsGet/RequestsGet.ts index cb7c5a59..258c3807 100644 --- a/packages/components/nodes/tools/RequestsGet/RequestsGet.ts +++ b/packages/components/nodes/tools/RequestsGet/RequestsGet.ts @@ -1,6 +1,7 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' import { desc, RequestParameters, RequestsGetTool } from './core' +import JSON5 from 'json5' const codeExample = `{ "id": { @@ -130,7 +131,7 @@ class RequestsGet_Tools implements INode { if (queryParamsSchema) obj.queryParamsSchema = queryParamsSchema if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) if (headers) { - const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) + const parsedHeaders = typeof headers === 'object' ? headers : JSON5.parse(stripHTMLFromToolInput(headers)) obj.headers = parsedHeaders } diff --git a/packages/components/nodes/tools/RequestsGet/core.ts b/packages/components/nodes/tools/RequestsGet/core.ts index 931a494e..b519341a 100644 --- a/packages/components/nodes/tools/RequestsGet/core.ts +++ b/packages/components/nodes/tools/RequestsGet/core.ts @@ -1,6 +1,7 @@ import { z } from 'zod' import { DynamicStructuredTool } from '../OpenAPIToolkit/core' import { secureFetch } from '../../../src/httpSecurity' +import JSON5 from 'json5' export const desc = `Use this when you need to execute a GET request to get data from a website.` @@ -22,7 +23,7 @@ const createRequestsGetSchema = (queryParamsSchema?: string) => { // If queryParamsSchema is provided, parse it and add dynamic query params if (queryParamsSchema) { try { - const parsedSchema = JSON.parse(queryParamsSchema) + const parsedSchema = JSON5.parse(queryParamsSchema) const queryParamsObject: Record = {} Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { @@ -108,7 +109,7 @@ export class RequestsGetTool extends DynamicStructuredTool { if (this.queryParamsSchema && params.queryParams && Object.keys(params.queryParams).length > 0) { try { - const parsedSchema = JSON.parse(this.queryParamsSchema) + const parsedSchema = JSON5.parse(this.queryParamsSchema) const pathParams: Array<{ key: string; value: string }> = [] Object.entries(params.queryParams).forEach(([key, value]) => { diff --git a/packages/components/nodes/tools/RequestsPost/RequestsPost.ts b/packages/components/nodes/tools/RequestsPost/RequestsPost.ts index 326084d9..ea9c8669 100644 --- a/packages/components/nodes/tools/RequestsPost/RequestsPost.ts +++ b/packages/components/nodes/tools/RequestsPost/RequestsPost.ts @@ -1,6 +1,7 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' import { RequestParameters, desc, RequestsPostTool } from './core' +import JSON5 from 'json5' const codeExample = `{ "name": { @@ -140,11 +141,11 @@ class RequestsPost_Tools implements INode { if (bodySchema) obj.bodySchema = stripHTMLFromToolInput(bodySchema) if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) if (headers) { - const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) + const parsedHeaders = typeof headers === 'object' ? headers : JSON5.parse(stripHTMLFromToolInput(headers)) obj.headers = parsedHeaders } if (body) { - const parsedBody = typeof body === 'object' ? body : JSON.parse(body) + const parsedBody = typeof body === 'object' ? body : JSON5.parse(body) obj.body = parsedBody } diff --git a/packages/components/nodes/tools/RequestsPost/core.ts b/packages/components/nodes/tools/RequestsPost/core.ts index bbffe937..5ee082c4 100644 --- a/packages/components/nodes/tools/RequestsPost/core.ts +++ b/packages/components/nodes/tools/RequestsPost/core.ts @@ -1,6 +1,7 @@ import { z } from 'zod' import { DynamicStructuredTool } from '../OpenAPIToolkit/core' import { secureFetch } from '../../../src/httpSecurity' +import JSON5 from 'json5' export const desc = `Use this when you want to execute a POST request to create or update a resource.` @@ -27,7 +28,7 @@ const createRequestsPostSchema = (bodySchema?: string) => { // If bodySchema is provided, parse it and add dynamic body params if (bodySchema) { try { - const parsedSchema = JSON.parse(bodySchema) + const parsedSchema = JSON5.parse(bodySchema) const bodyParamsObject: Record = {} Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => { diff --git a/packages/components/nodes/tools/RequestsPut/RequestsPut.ts b/packages/components/nodes/tools/RequestsPut/RequestsPut.ts index c2694015..ce5bfe38 100644 --- a/packages/components/nodes/tools/RequestsPut/RequestsPut.ts +++ b/packages/components/nodes/tools/RequestsPut/RequestsPut.ts @@ -1,6 +1,7 @@ import { INode, INodeData, INodeParams } from '../../../src/Interface' import { getBaseClasses, stripHTMLFromToolInput } from '../../../src/utils' import { RequestParameters, desc, RequestsPutTool } from './core' +import JSON5 from 'json5' const codeExample = `{ "name": { @@ -140,11 +141,11 @@ class RequestsPut_Tools implements INode { if (bodySchema) obj.bodySchema = stripHTMLFromToolInput(bodySchema) if (maxOutputLength) obj.maxOutputLength = parseInt(maxOutputLength, 10) if (headers) { - const parsedHeaders = typeof headers === 'object' ? headers : JSON.parse(stripHTMLFromToolInput(headers)) + const parsedHeaders = typeof headers === 'object' ? headers : JSON5.parse(stripHTMLFromToolInput(headers)) obj.headers = parsedHeaders } if (body) { - const parsedBody = typeof body === 'object' ? body : JSON.parse(body) + const parsedBody = typeof body === 'object' ? body : JSON5.parse(body) obj.body = parsedBody } diff --git a/packages/components/nodes/tools/RequestsPut/core.ts b/packages/components/nodes/tools/RequestsPut/core.ts index 28003f9d..0984be33 100644 --- a/packages/components/nodes/tools/RequestsPut/core.ts +++ b/packages/components/nodes/tools/RequestsPut/core.ts @@ -1,6 +1,7 @@ import { z } from 'zod' import { DynamicStructuredTool } from '../OpenAPIToolkit/core' import { secureFetch } from '../../../src/httpSecurity' +import JSON5 from 'json5' export const desc = `Use this when you want to execute a PUT request to update or replace a resource.` @@ -27,7 +28,7 @@ const createRequestsPutSchema = (bodySchema?: string) => { // If bodySchema is provided, parse it and add dynamic body params if (bodySchema) { try { - const parsedSchema = JSON.parse(bodySchema) + const parsedSchema = JSON5.parse(bodySchema) const bodyParamsObject: Record = {} Object.entries(parsedSchema).forEach(([key, config]: [string, any]) => {