refactor: Update code execution sandbox implementation across components
- Replaced NodeVM usage with a new createCodeExecutionSandbox function for improved sandbox management. - Enhanced JavaScript code execution with executeJavaScriptCode function, allowing for better handling of libraries and output streaming. - Updated multiple components to utilize the new sandboxing approach, ensuring consistent execution environment. - Added validation for UUIDs and URLs in various tools to enhance input safety. - Refactored input handling in CustomFunction and IfElseFunction to streamline variable management.
This commit is contained in:
parent
96a57a58e7
commit
b83742e806
|
|
@ -8,8 +8,7 @@ import {
|
||||||
INodeParams,
|
INodeParams,
|
||||||
IServerSideEventStreamer
|
IServerSideEventStreamer
|
||||||
} from '../../../src/Interface'
|
} from '../../../src/Interface'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { updateFlowState } from '../utils'
|
import { updateFlowState } from '../utils'
|
||||||
|
|
||||||
interface ICustomFunctionInputVariables {
|
interface ICustomFunctionInputVariables {
|
||||||
|
|
@ -19,9 +18,9 @@ interface ICustomFunctionInputVariables {
|
||||||
|
|
||||||
const exampleFunc = `/*
|
const exampleFunc = `/*
|
||||||
* You can use any libraries imported in Flowise
|
* You can use any libraries imported in Flowise
|
||||||
* You can use properties specified in Input Schema as variables. Ex: Property = userid, Variable = $userid
|
* You can use properties specified in Input Variables with the prefix $. For example: $foo
|
||||||
* You can get default flow config: $flow.sessionId, $flow.chatId, $flow.chatflowId, $flow.input, $flow.state
|
* You can get default flow config: $flow.sessionId, $flow.chatId, $flow.chatflowId, $flow.input, $flow.state
|
||||||
* You can get custom variables: $vars.<variable-name>
|
* You can get global variables: $vars.<variable-name>
|
||||||
* Must return a string value at the end of function
|
* Must return a string value at the end of function
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -161,55 +160,36 @@ class CustomFunction_Agentflow implements INode {
|
||||||
state: newState
|
state: newState
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: any = {
|
// Create additional sandbox variables for custom function inputs
|
||||||
$input: input,
|
const additionalSandbox: ICommonObject = {}
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
|
|
||||||
for (const item of functionInputVariables) {
|
for (const item of functionInputVariables) {
|
||||||
const variableName = item.variableName
|
const variableName = item.variableName
|
||||||
const variableValue = item.variableValue
|
const variableValue = item.variableValue
|
||||||
sandbox[`$${variableName}`] = variableValue
|
additionalSandbox[`$${variableName}`] = variableValue
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
const sandbox = createCodeExecutionSandbox(input, variables, flow, additionalSandbox)
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
// Setup streaming function if needed
|
||||||
console: 'inherit',
|
const streamOutput = isStreamable
|
||||||
sandbox,
|
? (output: string) => {
|
||||||
require: {
|
const sseStreamer: IServerSideEventStreamer = options.sseStreamer
|
||||||
external: { modules: deps },
|
sseStreamer.streamTokenEvent(chatId, output)
|
||||||
builtin: builtinDeps
|
}
|
||||||
},
|
: undefined
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${javascriptFunction}}()`, __dirname)
|
const response = await executeJavaScriptCode(javascriptFunction, sandbox, {
|
||||||
|
libraries: ['axios'],
|
||||||
|
streamOutput,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
let finalOutput = response
|
let finalOutput = response
|
||||||
if (typeof response === 'object') {
|
if (typeof response === 'object') {
|
||||||
finalOutput = JSON.stringify(response, null, 2)
|
finalOutput = JSON.stringify(response, null, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isStreamable) {
|
|
||||||
const sseStreamer: IServerSideEventStreamer = options.sseStreamer
|
|
||||||
sseStreamer.streamTokenEvent(chatId, finalOutput)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process template variables in state
|
// Process template variables in state
|
||||||
if (newState && Object.keys(newState).length > 0) {
|
if (newState && Object.keys(newState).length > 0) {
|
||||||
for (const key in newState) {
|
for (const key in newState) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, handleEscapeCharacters, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, handleEscapeCharacters, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
|
|
||||||
class CustomDocumentLoader_DocumentLoaders implements INode {
|
class CustomDocumentLoader_DocumentLoaders implements INode {
|
||||||
label: string
|
label: string
|
||||||
|
|
@ -106,44 +105,23 @@ class CustomDocumentLoader_DocumentLoaders implements INode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: any = {
|
// Create additional sandbox variables
|
||||||
$input: input,
|
const additionalSandbox: ICommonObject = {}
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
|
|
||||||
|
// Add input variables to sandbox
|
||||||
if (Object.keys(inputVars).length) {
|
if (Object.keys(inputVars).length) {
|
||||||
for (const item in inputVars) {
|
for (const item in inputVars) {
|
||||||
sandbox[`$${item}`] = inputVars[item]
|
additionalSandbox[`$${item}`] = inputVars[item]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
const sandbox = createCodeExecutionSandbox(input, variables, flow, additionalSandbox)
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${javascriptFunction}}()`, __dirname)
|
const response = await executeJavaScriptCode(javascriptFunction, sandbox, {
|
||||||
|
libraries: ['axios'],
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (output === 'document' && Array.isArray(response)) {
|
if (output === 'document' && Array.isArray(response)) {
|
||||||
if (response.length === 0) return response
|
if (response.length === 0) return response
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeParams } from '../../../src/Interface'
|
||||||
import { getBaseClasses, transformBracesWithColon } from '../../../src/utils'
|
import { getBaseClasses, transformBracesWithColon, getVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate } from '@langchain/core/prompts'
|
import { ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate } from '@langchain/core/prompts'
|
||||||
import { getVM } from '../../sequentialagents/commonUtils'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
const defaultFunc = `const { AIMessage, HumanMessage, ToolMessage } = require('@langchain/core/messages');
|
const defaultFunc = `const { AIMessage, HumanMessage, ToolMessage } = require('@langchain/core/messages');
|
||||||
|
|
||||||
|
|
@ -120,13 +119,29 @@ class ChatPromptTemplate_Prompts implements INode {
|
||||||
) {
|
) {
|
||||||
const appDataSource = options.appDataSource as DataSource
|
const appDataSource = options.appDataSource as DataSource
|
||||||
const databaseEntities = options.databaseEntities as IDatabaseEntity
|
const databaseEntities = options.databaseEntities as IDatabaseEntity
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, {})
|
const variables = await getVars(appDataSource, databaseEntities, nodeData, options)
|
||||||
|
const flow = {
|
||||||
|
chatflowId: options.chatflowid,
|
||||||
|
sessionId: options.sessionId,
|
||||||
|
chatId: options.chatId
|
||||||
|
}
|
||||||
|
|
||||||
|
const sandbox = createCodeExecutionSandbox('', variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${messageHistoryCode}}()`, __dirname)
|
const response = await executeJavaScriptCode(messageHistoryCode, sandbox, {
|
||||||
if (!Array.isArray(response)) throw new Error('Returned message history must be an array')
|
libraries: ['axios', '@langchain/core'],
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
const parsedResponse = JSON.parse(response)
|
||||||
|
|
||||||
|
if (!Array.isArray(parsedResponse)) {
|
||||||
|
throw new Error('Returned message history must be an array')
|
||||||
|
}
|
||||||
prompt = ChatPromptTemplate.fromMessages([
|
prompt = ChatPromptTemplate.fromMessages([
|
||||||
SystemMessagePromptTemplate.fromTemplate(systemMessagePrompt),
|
SystemMessagePromptTemplate.fromTemplate(systemMessagePrompt),
|
||||||
...response,
|
...parsedResponse,
|
||||||
HumanMessagePromptTemplate.fromTemplate(humanMessagePrompt)
|
HumanMessagePromptTemplate.fromTemplate(humanMessagePrompt)
|
||||||
])
|
])
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,12 @@ import {
|
||||||
handleEscapeCharacters,
|
handleEscapeCharacters,
|
||||||
prepareSandboxVars,
|
prepareSandboxVars,
|
||||||
removeInvalidImageMarkdown,
|
removeInvalidImageMarkdown,
|
||||||
transformBracesWithColon
|
transformBracesWithColon,
|
||||||
|
executeJavaScriptCode,
|
||||||
|
createCodeExecutionSandbox
|
||||||
} from '../../../src/utils'
|
} from '../../../src/utils'
|
||||||
import {
|
import {
|
||||||
customGet,
|
customGet,
|
||||||
getVM,
|
|
||||||
processImageMessage,
|
processImageMessage,
|
||||||
transformObjectPropertyToFunction,
|
transformObjectPropertyToFunction,
|
||||||
filterConversationHistory,
|
filterConversationHistory,
|
||||||
|
|
@ -936,9 +937,13 @@ const getReturnOutput = async (nodeData: INodeData, input: string, options: ICom
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
}
|
}
|
||||||
} else if (selectedTab === 'updateStateMemoryCode' && updateStateMemoryCode) {
|
} else if (selectedTab === 'updateStateMemoryCode' && updateStateMemoryCode) {
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, flow)
|
const sandbox = createCodeExecutionSandbox(input, variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${updateStateMemoryCode}}()`, __dirname)
|
const response = await executeJavaScriptCode(updateStateMemoryCode, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response !== 'object') throw new Error('Return output must be an object')
|
if (typeof response !== 'object') throw new Error('Return output must be an object')
|
||||||
return response
|
return response
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import {
|
||||||
ISeqAgentNode,
|
ISeqAgentNode,
|
||||||
ISeqAgentsState
|
ISeqAgentsState
|
||||||
} from '../../../src/Interface'
|
} from '../../../src/Interface'
|
||||||
import { checkCondition, customGet, getVM } from '../commonUtils'
|
import { checkCondition, customGet } from '../commonUtils'
|
||||||
import { getVars, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, prepareSandboxVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
|
|
||||||
const howToUseCode = `
|
const howToUseCode = `
|
||||||
1. Must return a string value at the end of function. For example:
|
1. Must return a string value at the end of function. For example:
|
||||||
|
|
@ -279,9 +279,13 @@ const runCondition = async (nodeData: INodeData, input: string, options: ICommon
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedTab === 'conditionFunction' && conditionFunction) {
|
if (selectedTab === 'conditionFunction' && conditionFunction) {
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, flow)
|
const sandbox = createCodeExecutionSandbox(input, variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${conditionFunction}}()`, __dirname)
|
const response = await executeJavaScriptCode(conditionFunction, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response !== 'string') throw new Error('Condition function must return a string')
|
if (typeof response !== 'string') throw new Error('Condition function must return a string')
|
||||||
return response
|
return response
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,19 @@ import {
|
||||||
ISeqAgentNode,
|
ISeqAgentNode,
|
||||||
ISeqAgentsState
|
ISeqAgentsState
|
||||||
} from '../../../src/Interface'
|
} from '../../../src/Interface'
|
||||||
import { getInputVariables, getVars, handleEscapeCharacters, prepareSandboxVars, transformBracesWithColon } from '../../../src/utils'
|
import {
|
||||||
|
getInputVariables,
|
||||||
|
getVars,
|
||||||
|
handleEscapeCharacters,
|
||||||
|
prepareSandboxVars,
|
||||||
|
transformBracesWithColon,
|
||||||
|
executeJavaScriptCode,
|
||||||
|
createCodeExecutionSandbox
|
||||||
|
} from '../../../src/utils'
|
||||||
import {
|
import {
|
||||||
checkCondition,
|
checkCondition,
|
||||||
convertStructuredSchemaToZod,
|
convertStructuredSchemaToZod,
|
||||||
customGet,
|
customGet,
|
||||||
getVM,
|
|
||||||
transformObjectPropertyToFunction,
|
transformObjectPropertyToFunction,
|
||||||
filterConversationHistory,
|
filterConversationHistory,
|
||||||
restructureMessages
|
restructureMessages
|
||||||
|
|
@ -539,9 +546,13 @@ const runCondition = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedTab === 'conditionFunction' && conditionFunction) {
|
if (selectedTab === 'conditionFunction' && conditionFunction) {
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, flow)
|
const sandbox = createCodeExecutionSandbox(input, variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${conditionFunction}}()`, __dirname)
|
const response = await executeJavaScriptCode(conditionFunction, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response !== 'string') throw new Error('Condition function must return a string')
|
if (typeof response !== 'string') throw new Error('Condition function must return a string')
|
||||||
return response
|
return response
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, handleEscapeCharacters, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, handleEscapeCharacters, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeParams, ISeqAgentNode, ISeqAgentsState } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeParams, ISeqAgentNode, ISeqAgentsState } from '../../../src/Interface'
|
||||||
import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages'
|
import { AIMessage, BaseMessage, HumanMessage } from '@langchain/core/messages'
|
||||||
import { customGet } from '../commonUtils'
|
import { customGet } from '../commonUtils'
|
||||||
|
|
@ -154,44 +153,22 @@ class CustomFunction_SeqAgents implements INode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: any = {
|
// Create additional sandbox variables
|
||||||
$input: input,
|
const additionalSandbox: ICommonObject = {}
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
|
|
||||||
|
// Add input variables to sandbox
|
||||||
if (Object.keys(inputVars).length) {
|
if (Object.keys(inputVars).length) {
|
||||||
for (const item in inputVars) {
|
for (const item in inputVars) {
|
||||||
sandbox[`$${item}`] = inputVars[item]
|
additionalSandbox[`$${item}`] = inputVars[item]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
const sandbox = createCodeExecutionSandbox(input, variables, flow, additionalSandbox)
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${javascriptFunction}}()`, __dirname)
|
const response = await executeJavaScriptCode(javascriptFunction, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (returnValueAs === 'stateObj') {
|
if (returnValueAs === 'stateObj') {
|
||||||
if (typeof response !== 'object') {
|
if (typeof response !== 'object') {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,6 @@
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import {
|
import { getCredentialData, getCredentialParam, getVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
availableDependencies,
|
import { isValidUUID, isValidURL } from '../../../src/validator'
|
||||||
defaultAllowBuiltInDep,
|
|
||||||
getCredentialData,
|
|
||||||
getCredentialParam,
|
|
||||||
getVars,
|
|
||||||
prepareSandboxVars
|
|
||||||
} from '../../../src/utils'
|
|
||||||
import {
|
import {
|
||||||
ICommonObject,
|
ICommonObject,
|
||||||
IDatabaseEntity,
|
IDatabaseEntity,
|
||||||
|
|
@ -177,6 +170,16 @@ class ExecuteFlow_SeqAgents implements INode {
|
||||||
const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)
|
const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)
|
||||||
const returnValueAs = nodeData.inputs?.returnValueAs as string
|
const returnValueAs = nodeData.inputs?.returnValueAs as string
|
||||||
|
|
||||||
|
// Validate selectedFlowId is a valid UUID
|
||||||
|
if (!selectedFlowId || !isValidUUID(selectedFlowId)) {
|
||||||
|
throw new Error('Invalid flow ID: must be a valid UUID')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate baseURL is a valid URL
|
||||||
|
if (!baseURL || !isValidURL(baseURL)) {
|
||||||
|
throw new Error('Invalid base URL: must be a valid URL')
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
const chatflowApiKey = getCredentialParam('chatflowApiKey', credentialData, nodeData)
|
const chatflowApiKey = getCredentialParam('chatflowApiKey', credentialData, nodeData)
|
||||||
|
|
||||||
|
|
@ -233,18 +236,13 @@ class ExecuteFlow_SeqAgents implements INode {
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: ICommonObject = {
|
// Create additional sandbox variables
|
||||||
$input: flowInput,
|
const additionalSandbox: ICommonObject = {
|
||||||
$callOptions: callOptions,
|
$callOptions: callOptions,
|
||||||
$callBody: body,
|
$callBody: body
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
}
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
const sandbox = createCodeExecutionSandbox(flowInput, variables, flow, additionalSandbox)
|
||||||
|
|
||||||
const code = `
|
const code = `
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
|
|
@ -264,27 +262,11 @@ class ExecuteFlow_SeqAgents implements INode {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
let response = await vm.run(`module.exports = async function() {${code}}()`, __dirname)
|
let response = await executeJavaScriptCode(code, sandbox, {
|
||||||
|
useSandbox: false,
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response === 'object') {
|
if (typeof response === 'object') {
|
||||||
response = JSON.stringify(response)
|
response = JSON.stringify(response)
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,13 @@ import {
|
||||||
getVars,
|
getVars,
|
||||||
handleEscapeCharacters,
|
handleEscapeCharacters,
|
||||||
prepareSandboxVars,
|
prepareSandboxVars,
|
||||||
transformBracesWithColon
|
transformBracesWithColon,
|
||||||
|
executeJavaScriptCode,
|
||||||
|
createCodeExecutionSandbox
|
||||||
} from '../../../src/utils'
|
} from '../../../src/utils'
|
||||||
import {
|
import {
|
||||||
convertStructuredSchemaToZod,
|
convertStructuredSchemaToZod,
|
||||||
customGet,
|
customGet,
|
||||||
getVM,
|
|
||||||
processImageMessage,
|
processImageMessage,
|
||||||
transformObjectPropertyToFunction,
|
transformObjectPropertyToFunction,
|
||||||
filterConversationHistory,
|
filterConversationHistory,
|
||||||
|
|
@ -708,9 +709,13 @@ const getReturnOutput = async (nodeData: INodeData, input: string, options: ICom
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
}
|
}
|
||||||
} else if (selectedTab === 'updateStateMemoryCode' && updateStateMemoryCode) {
|
} else if (selectedTab === 'updateStateMemoryCode' && updateStateMemoryCode) {
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, flow)
|
const sandbox = createCodeExecutionSandbox(input, variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${updateStateMemoryCode}}()`, __dirname)
|
const response = await executeJavaScriptCode(updateStateMemoryCode, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response !== 'object') throw new Error('Return output must be an object')
|
if (typeof response !== 'object') throw new Error('Return output must be an object')
|
||||||
return response
|
return response
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
import { START } from '@langchain/langgraph'
|
import { START } from '@langchain/langgraph'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeParams, ISeqAgentNode } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeParams, ISeqAgentNode } from '../../../src/Interface'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
|
|
||||||
const defaultFunc = `{
|
const defaultFunc = `{
|
||||||
aggregate: {
|
aggregate: {
|
||||||
value: (x, y) => x.concat(y), // here we append the new message to the existing messages
|
value: (x, y) => x.concat(y), // here we append the new message to the existing messages
|
||||||
default: () => []
|
default: () => []
|
||||||
|
},
|
||||||
|
replacedValue: {
|
||||||
|
value: (x, y) => y ?? x,
|
||||||
|
default: () => null
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
|
@ -198,37 +201,13 @@ class State_SeqAgents implements INode {
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: any = {
|
const sandbox = createCodeExecutionSandbox('', variables, flow)
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {return ${stateMemoryCode}}()`, __dirname)
|
const response = await executeJavaScriptCode(`return ${stateMemoryCode}`, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response !== 'object') throw new Error('State must be an object')
|
if (typeof response !== 'object') throw new Error('State must be an object')
|
||||||
const returnOutput: ISeqAgentNode = {
|
const returnOutput: ISeqAgentNode = {
|
||||||
id: nodeData.id,
|
id: nodeData.id,
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ import { RunnableConfig } from '@langchain/core/runnables'
|
||||||
import { ARTIFACTS_PREFIX, SOURCE_DOCUMENTS_PREFIX, TOOL_ARGS_PREFIX } from '../../../src/agents'
|
import { ARTIFACTS_PREFIX, SOURCE_DOCUMENTS_PREFIX, TOOL_ARGS_PREFIX } from '../../../src/agents'
|
||||||
import { Document } from '@langchain/core/documents'
|
import { Document } from '@langchain/core/documents'
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { MessagesState, RunnableCallable, customGet, getVM } from '../commonUtils'
|
import { MessagesState, RunnableCallable, customGet } from '../commonUtils'
|
||||||
import { getVars, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, prepareSandboxVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ChatPromptTemplate } from '@langchain/core/prompts'
|
import { ChatPromptTemplate } from '@langchain/core/prompts'
|
||||||
|
|
||||||
const defaultApprovalPrompt = `You are about to execute tool: {tools}. Ask if user want to proceed`
|
const defaultApprovalPrompt = `You are about to execute tool: {tools}. Ask if user want to proceed`
|
||||||
|
|
@ -572,9 +572,13 @@ const getReturnOutput = async (
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
}
|
}
|
||||||
} else if (selectedTab === 'updateStateMemoryCode' && updateStateMemoryCode) {
|
} else if (selectedTab === 'updateStateMemoryCode' && updateStateMemoryCode) {
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, flow)
|
const sandbox = createCodeExecutionSandbox(input, variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${updateStateMemoryCode}}()`, __dirname)
|
const response = await executeJavaScriptCode(updateStateMemoryCode, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response !== 'object') throw new Error('Return output must be an object')
|
if (typeof response !== 'object') throw new Error('Return output must be an object')
|
||||||
return response
|
return response
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { get } from 'lodash'
|
import { get } from 'lodash'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { StructuredTool } from '@langchain/core/tools'
|
import { StructuredTool } from '@langchain/core/tools'
|
||||||
import { ChatMistralAI } from '@langchain/mistralai'
|
import { ChatMistralAI } from '@langchain/mistralai'
|
||||||
import { ChatAnthropic } from '@langchain/anthropic'
|
import { ChatAnthropic } from '@langchain/anthropic'
|
||||||
|
|
@ -17,7 +16,7 @@ import {
|
||||||
IVisionChatModal,
|
IVisionChatModal,
|
||||||
ConversationHistorySelection
|
ConversationHistorySelection
|
||||||
} from '../../src/Interface'
|
} from '../../src/Interface'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, prepareSandboxVars } from '../../src/utils'
|
import { getVars, executeJavaScriptCode, createCodeExecutionSandbox } from '../../src/utils'
|
||||||
import { ChatPromptTemplate, BaseMessagePromptTemplateLike } from '@langchain/core/prompts'
|
import { ChatPromptTemplate, BaseMessagePromptTemplateLike } from '@langchain/core/prompts'
|
||||||
|
|
||||||
export const checkCondition = (input: string | number | undefined, condition: string, value: string | number = ''): boolean => {
|
export const checkCondition = (input: string | number | undefined, condition: string, value: string | number = ''): boolean => {
|
||||||
|
|
@ -150,46 +149,6 @@ export const processImageMessage = async (llm: BaseChatModel, nodeData: INodeDat
|
||||||
return multiModalMessageContent
|
return multiModalMessageContent
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getVM = async (
|
|
||||||
appDataSource: DataSource,
|
|
||||||
databaseEntities: IDatabaseEntity,
|
|
||||||
nodeData: INodeData,
|
|
||||||
options: ICommonObject,
|
|
||||||
flow: ICommonObject
|
|
||||||
) => {
|
|
||||||
const variables = await getVars(appDataSource, databaseEntities, nodeData, options)
|
|
||||||
|
|
||||||
let sandbox: any = {
|
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
return new NodeVM(nodeVMOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const customGet = (obj: any, path: string) => {
|
export const customGet = (obj: any, path: string) => {
|
||||||
if (path.includes('[-1]')) {
|
if (path.includes('[-1]')) {
|
||||||
const parts = path.split('.')
|
const parts = path.split('.')
|
||||||
|
|
@ -426,9 +385,21 @@ export const checkMessageHistory = async (
|
||||||
if (messageHistory) {
|
if (messageHistory) {
|
||||||
const appDataSource = options.appDataSource as DataSource
|
const appDataSource = options.appDataSource as DataSource
|
||||||
const databaseEntities = options.databaseEntities as IDatabaseEntity
|
const databaseEntities = options.databaseEntities as IDatabaseEntity
|
||||||
const vm = await getVM(appDataSource, databaseEntities, nodeData, options, {})
|
|
||||||
|
const variables = await getVars(appDataSource, databaseEntities, nodeData, options)
|
||||||
|
const flow = {
|
||||||
|
chatflowId: options.chatflowid,
|
||||||
|
sessionId: options.sessionId,
|
||||||
|
chatId: options.chatId
|
||||||
|
}
|
||||||
|
|
||||||
|
const sandbox = createCodeExecutionSandbox('', variables, flow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${messageHistory}}()`, __dirname)
|
const response = await executeJavaScriptCode(messageHistory, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (!Array.isArray(response)) throw new Error('Returned message history must be an array')
|
if (!Array.isArray(response)) throw new Error('Returned message history must be an array')
|
||||||
if (sysPrompt) {
|
if (sysPrompt) {
|
||||||
// insert at index 1
|
// insert at index 1
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { RunnableConfig } from '@langchain/core/runnables'
|
import { RunnableConfig } from '@langchain/core/runnables'
|
||||||
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
||||||
import { StructuredTool } from '@langchain/core/tools'
|
import { StructuredTool } from '@langchain/core/tools'
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { getCredentialData, getCredentialParam, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
|
import { isValidUUID, isValidURL } from '../../../src/validator'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
class AgentAsTool_Tools implements INode {
|
class AgentAsTool_Tools implements INode {
|
||||||
|
|
@ -160,6 +160,16 @@ class AgentAsTool_Tools implements INode {
|
||||||
|
|
||||||
const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)
|
const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)
|
||||||
|
|
||||||
|
// Validate agentflowid is a valid UUID
|
||||||
|
if (!selectedAgentflowId || !isValidUUID(selectedAgentflowId)) {
|
||||||
|
throw new Error('Invalid agentflow ID: must be a valid UUID')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate baseURL is a valid URL
|
||||||
|
if (!baseURL || !isValidURL(baseURL)) {
|
||||||
|
throw new Error('Invalid base URL: must be a valid URL')
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
const agentflowApiKey = getCredentialParam('agentflowApiKey', credentialData, nodeData)
|
const agentflowApiKey = getCredentialParam('agentflowApiKey', credentialData, nodeData)
|
||||||
|
|
||||||
|
|
@ -326,16 +336,6 @@ class AgentflowTool extends StructuredTool {
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox = {
|
|
||||||
$callOptions: options,
|
|
||||||
$callBody: body,
|
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const code = `
|
const code = `
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
const url = "${this.baseURL}/api/v1/prediction/${this.agentflowid}";
|
const url = "${this.baseURL}/api/v1/prediction/${this.agentflowid}";
|
||||||
|
|
@ -353,26 +353,19 @@ try {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const vmOptions = {
|
// Create additional sandbox variables
|
||||||
console: 'inherit',
|
const additionalSandbox: ICommonObject = {
|
||||||
sandbox,
|
$callOptions: options,
|
||||||
require: {
|
$callBody: body
|
||||||
external: { modules: deps },
|
}
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
const sandbox = createCodeExecutionSandbox('', [], {}, additionalSandbox)
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
const response = await executeJavaScriptCode(code, sandbox, {
|
||||||
|
useSandbox: false,
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
} as any
|
})
|
||||||
|
|
||||||
const vm = new NodeVM(vmOptions)
|
|
||||||
const response = await vm.run(`module.exports = async function() {${code}}()`, __dirname)
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { RunnableConfig } from '@langchain/core/runnables'
|
import { RunnableConfig } from '@langchain/core/runnables'
|
||||||
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
||||||
import { StructuredTool } from '@langchain/core/tools'
|
import { StructuredTool } from '@langchain/core/tools'
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOptionsValue, INodeParams } from '../../../src/Interface'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { getCredentialData, getCredentialParam, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
|
import { isValidUUID, isValidURL } from '../../../src/validator'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
class ChatflowTool_Tools implements INode {
|
class ChatflowTool_Tools implements INode {
|
||||||
|
|
@ -168,6 +168,16 @@ class ChatflowTool_Tools implements INode {
|
||||||
|
|
||||||
const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)
|
const baseURL = (nodeData.inputs?.baseURL as string) || (options.baseURL as string)
|
||||||
|
|
||||||
|
// Validate selectedChatflowId is a valid UUID
|
||||||
|
if (!selectedChatflowId || !isValidUUID(selectedChatflowId)) {
|
||||||
|
throw new Error('Invalid chatflow ID: must be a valid UUID')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate baseURL is a valid URL
|
||||||
|
if (!baseURL || !isValidURL(baseURL)) {
|
||||||
|
throw new Error('Invalid base URL: must be a valid URL')
|
||||||
|
}
|
||||||
|
|
||||||
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
const credentialData = await getCredentialData(nodeData.credential ?? '', options)
|
||||||
const chatflowApiKey = getCredentialParam('chatflowApiKey', credentialData, nodeData)
|
const chatflowApiKey = getCredentialParam('chatflowApiKey', credentialData, nodeData)
|
||||||
|
|
||||||
|
|
@ -334,16 +344,6 @@ class ChatflowTool extends StructuredTool {
|
||||||
body: JSON.stringify(body)
|
body: JSON.stringify(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox = {
|
|
||||||
$callOptions: options,
|
|
||||||
$callBody: body,
|
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const code = `
|
const code = `
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
const url = "${this.baseURL}/api/v1/prediction/${this.chatflowid}";
|
const url = "${this.baseURL}/api/v1/prediction/${this.chatflowid}";
|
||||||
|
|
@ -361,26 +361,19 @@ try {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const vmOptions = {
|
// Create additional sandbox variables
|
||||||
console: 'inherit',
|
const additionalSandbox: ICommonObject = {
|
||||||
sandbox,
|
$callOptions: options,
|
||||||
require: {
|
$callBody: body
|
||||||
external: { modules: deps },
|
}
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
const sandbox = createCodeExecutionSandbox('', [], {}, additionalSandbox)
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
const response = await executeJavaScriptCode(code, sandbox, {
|
||||||
|
useSandbox: false,
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
} as any
|
})
|
||||||
|
|
||||||
const vm = new NodeVM(vmOptions)
|
|
||||||
const response = await vm.run(`module.exports = async function() {${code}}()`, __dirname)
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, INode, INodeData, INodeParams } from '../../../src/Interface'
|
||||||
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
import { getBaseClasses, getCredentialData, getCredentialParam } from '../../../src/utils'
|
||||||
import { StructuredTool, ToolInputParsingException, ToolParams } from '@langchain/core/tools'
|
import { StructuredTool, ToolInputParsingException, ToolParams } from '@langchain/core/tools'
|
||||||
import { CodeInterpreter } from '@e2b/code-interpreter'
|
import { Sandbox } from '@e2b/code-interpreter'
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { addSingleFileToStorage } from '../../../src/storageUtils'
|
import { addSingleFileToStorage } from '../../../src/storageUtils'
|
||||||
import { CallbackManager, CallbackManagerForToolRun, Callbacks, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
import { CallbackManager, CallbackManagerForToolRun, Callbacks, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
||||||
|
|
@ -107,7 +107,7 @@ export class E2BTool extends StructuredTool {
|
||||||
|
|
||||||
description = DESC
|
description = DESC
|
||||||
|
|
||||||
instance: CodeInterpreter
|
instance: Sandbox
|
||||||
|
|
||||||
apiKey: string
|
apiKey: string
|
||||||
|
|
||||||
|
|
@ -204,8 +204,8 @@ export class E2BTool extends StructuredTool {
|
||||||
flowConfig = { ...this.flowObj, ...flowConfig }
|
flowConfig = { ...this.flowObj, ...flowConfig }
|
||||||
try {
|
try {
|
||||||
if ('input' in arg) {
|
if ('input' in arg) {
|
||||||
this.instance = await CodeInterpreter.create({ apiKey: this.apiKey })
|
this.instance = await Sandbox.create({ apiKey: this.apiKey })
|
||||||
const execution = await this.instance.notebook.execCell(arg?.input)
|
const execution = await this.instance.runCode(arg?.input, { language: 'python' })
|
||||||
|
|
||||||
const artifacts = []
|
const artifacts = []
|
||||||
for (const result of execution.results) {
|
for (const result of execution.results) {
|
||||||
|
|
@ -251,8 +251,6 @@ export class E2BTool extends StructuredTool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.instance.close()
|
|
||||||
|
|
||||||
let output = ''
|
let output = ''
|
||||||
|
|
||||||
if (execution.text) output = execution.text
|
if (execution.text) output = execution.text
|
||||||
|
|
@ -267,7 +265,7 @@ export class E2BTool extends StructuredTool {
|
||||||
return 'No input provided'
|
return 'No input provided'
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (this.instance) this.instance.close()
|
if (this.instance) this.instance.kill()
|
||||||
return typeof e === 'string' ? e : JSON.stringify(e, null, 2)
|
return typeof e === 'string' ? e : JSON.stringify(e, null, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { RunnableConfig } from '@langchain/core/runnables'
|
import { RunnableConfig } from '@langchain/core/runnables'
|
||||||
import { StructuredTool, ToolParams } from '@langchain/core/tools'
|
import { StructuredTool, ToolParams } from '@langchain/core/tools'
|
||||||
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, prepareSandboxVars } from '../../../src/utils'
|
import { executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ICommonObject } from '../../../src/Interface'
|
import { ICommonObject } from '../../../src/Interface'
|
||||||
|
|
||||||
class ToolInputParsingException extends Error {
|
class ToolInputParsingException extends Error {
|
||||||
|
|
@ -111,46 +110,23 @@ export class DynamicStructuredTool<
|
||||||
_?: CallbackManagerForToolRun,
|
_?: CallbackManagerForToolRun,
|
||||||
flowConfig?: { sessionId?: string; chatId?: string; input?: string; state?: ICommonObject }
|
flowConfig?: { sessionId?: string; chatId?: string; input?: string; state?: ICommonObject }
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
let sandbox: any = {
|
// Create additional sandbox variables for tool arguments
|
||||||
util: undefined,
|
const additionalSandbox: ICommonObject = {}
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
if (typeof arg === 'object' && Object.keys(arg).length) {
|
if (typeof arg === 'object' && Object.keys(arg).length) {
|
||||||
for (const item in arg) {
|
for (const item in arg) {
|
||||||
sandbox[`$${item}`] = arg[item]
|
additionalSandbox[`$${item}`] = arg[item]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(this.variables)
|
// Prepare flow object for sandbox
|
||||||
|
const flow = this.flowObj ? { ...this.flowObj, ...flowConfig } : {}
|
||||||
|
|
||||||
// inject flow properties
|
const sandbox = createCodeExecutionSandbox('', this.variables || [], flow, additionalSandbox)
|
||||||
if (this.flowObj) {
|
|
||||||
sandbox['$flow'] = { ...this.flowObj, ...flowConfig }
|
|
||||||
}
|
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
const response = await executeJavaScriptCode(this.code, sandbox, {
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
} as any
|
})
|
||||||
|
|
||||||
const vm = new NodeVM(options)
|
|
||||||
const response = await vm.run(`module.exports = async function() {${this.code}}()`, __dirname)
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { RequestInit } from 'node-fetch'
|
import { RequestInit } from 'node-fetch'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { RunnableConfig } from '@langchain/core/runnables'
|
import { RunnableConfig } from '@langchain/core/runnables'
|
||||||
import { StructuredTool, ToolParams } from '@langchain/core/tools'
|
import { StructuredTool, ToolParams } from '@langchain/core/tools'
|
||||||
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
import { CallbackManagerForToolRun, Callbacks, CallbackManager, parseCallbackConfigArg } from '@langchain/core/callbacks/manager'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, prepareSandboxVars } from '../../../src/utils'
|
import { executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ICommonObject } from '../../../src/Interface'
|
import { ICommonObject } from '../../../src/Interface'
|
||||||
|
|
||||||
const removeNulls = (obj: Record<string, any>) => {
|
const removeNulls = (obj: Record<string, any>) => {
|
||||||
|
|
@ -217,32 +216,22 @@ export class DynamicStructuredTool<
|
||||||
_?: CallbackManagerForToolRun,
|
_?: CallbackManagerForToolRun,
|
||||||
flowConfig?: { sessionId?: string; chatId?: string; input?: string; state?: ICommonObject }
|
flowConfig?: { sessionId?: string; chatId?: string; input?: string; state?: ICommonObject }
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
let sandbox: any = {
|
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
let processedArg = { ...arg }
|
let processedArg = { ...arg }
|
||||||
|
|
||||||
if (this.removeNulls && typeof processedArg === 'object' && processedArg !== null) {
|
if (this.removeNulls && typeof processedArg === 'object' && processedArg !== null) {
|
||||||
processedArg = removeNulls(processedArg)
|
processedArg = removeNulls(processedArg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create additional sandbox variables for tool arguments
|
||||||
|
const additionalSandbox: ICommonObject = {}
|
||||||
|
|
||||||
if (typeof processedArg === 'object' && Object.keys(processedArg).length) {
|
if (typeof processedArg === 'object' && Object.keys(processedArg).length) {
|
||||||
for (const item in processedArg) {
|
for (const item in processedArg) {
|
||||||
sandbox[`$${item}`] = processedArg[item]
|
additionalSandbox[`$${item}`] = processedArg[item]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(this.variables)
|
// Prepare HTTP request options
|
||||||
|
|
||||||
// inject flow properties
|
|
||||||
if (this.flowObj) {
|
|
||||||
sandbox['$flow'] = { ...this.flowObj, ...flowConfig }
|
|
||||||
}
|
|
||||||
|
|
||||||
const callOptions: RequestInit = {
|
const callOptions: RequestInit = {
|
||||||
method: this.method,
|
method: this.method,
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -253,31 +242,20 @@ export class DynamicStructuredTool<
|
||||||
if (arg.RequestBody && this.method.toUpperCase() !== 'GET') {
|
if (arg.RequestBody && this.method.toUpperCase() !== 'GET') {
|
||||||
callOptions.body = JSON.stringify(arg.RequestBody)
|
callOptions.body = JSON.stringify(arg.RequestBody)
|
||||||
}
|
}
|
||||||
sandbox['$options'] = callOptions
|
additionalSandbox['$options'] = callOptions
|
||||||
|
|
||||||
|
// Generate complete URL
|
||||||
const completeUrl = getUrl(this.baseUrl, arg)
|
const completeUrl = getUrl(this.baseUrl, arg)
|
||||||
sandbox['$url'] = completeUrl
|
additionalSandbox['$url'] = completeUrl
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
// Prepare flow object for sandbox
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
const flow = this.flowObj ? { ...this.flowObj, ...flowConfig } : {}
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const options = {
|
const sandbox = createCodeExecutionSandbox('', this.variables || [], flow, additionalSandbox)
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
const response = await executeJavaScriptCode(this.customCode || defaultCode, sandbox, {
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
timeout: 10000
|
||||||
} as any
|
})
|
||||||
|
|
||||||
const vm = new NodeVM(options)
|
|
||||||
const response = await vm.run(`module.exports = async function() {${this.customCode || defaultCode}}()`, __dirname)
|
|
||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { flatten } from 'lodash'
|
import { flatten } from 'lodash'
|
||||||
import { type StructuredTool } from '@langchain/core/tools'
|
import { type StructuredTool } from '@langchain/core/tools'
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, handleEscapeCharacters, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, handleEscapeCharacters, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
|
||||||
|
|
||||||
class CustomFunction_Utilities implements INode {
|
class CustomFunction_Utilities implements INode {
|
||||||
|
|
@ -118,45 +117,24 @@ class CustomFunction_Utilities implements INode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: any = {
|
// Create additional sandbox variables
|
||||||
$input: input,
|
const additionalSandbox: ICommonObject = {
|
||||||
util: undefined,
|
$tools: tools
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
}
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
sandbox['$tools'] = tools
|
|
||||||
|
|
||||||
|
// Add input variables to sandbox
|
||||||
if (Object.keys(inputVars).length) {
|
if (Object.keys(inputVars).length) {
|
||||||
for (const item in inputVars) {
|
for (const item in inputVars) {
|
||||||
sandbox[`$${item}`] = inputVars[item]
|
additionalSandbox[`$${item}`] = inputVars[item]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
const sandbox = createCodeExecutionSandbox(input, variables, flow, additionalSandbox)
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
const response = await vm.run(`module.exports = async function() {${javascriptFunction}}()`, __dirname)
|
const response = await executeJavaScriptCode(javascriptFunction, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (typeof response === 'string' && !isEndingNode) {
|
if (typeof response === 'string' && !isEndingNode) {
|
||||||
return handleEscapeCharacters(response, false)
|
return handleEscapeCharacters(response, false)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { NodeVM } from '@flowiseai/nodevm'
|
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { availableDependencies, defaultAllowBuiltInDep, getVars, handleEscapeCharacters, prepareSandboxVars } from '../../../src/utils'
|
import { getVars, handleEscapeCharacters, executeJavaScriptCode, createCodeExecutionSandbox } from '../../../src/utils'
|
||||||
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
|
import { ICommonObject, IDatabaseEntity, INode, INodeData, INodeOutputsValue, INodeParams } from '../../../src/Interface'
|
||||||
|
|
||||||
class IfElseFunction_Utilities implements INode {
|
class IfElseFunction_Utilities implements INode {
|
||||||
|
|
@ -119,48 +118,30 @@ class IfElseFunction_Utilities implements INode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let sandbox: any = {
|
// Create additional sandbox variables
|
||||||
$input: input,
|
const additionalSandbox: ICommonObject = {}
|
||||||
util: undefined,
|
|
||||||
Symbol: undefined,
|
|
||||||
child_process: undefined,
|
|
||||||
fs: undefined,
|
|
||||||
process: undefined
|
|
||||||
}
|
|
||||||
sandbox['$vars'] = prepareSandboxVars(variables)
|
|
||||||
sandbox['$flow'] = flow
|
|
||||||
|
|
||||||
|
// Add input variables to sandbox
|
||||||
if (Object.keys(inputVars).length) {
|
if (Object.keys(inputVars).length) {
|
||||||
for (const item in inputVars) {
|
for (const item in inputVars) {
|
||||||
sandbox[`$${item}`] = inputVars[item]
|
additionalSandbox[`$${item}`] = inputVars[item]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
const sandbox = createCodeExecutionSandbox(input, variables, flow, additionalSandbox)
|
||||||
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
|
||||||
: defaultAllowBuiltInDep
|
|
||||||
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
|
||||||
const deps = availableDependencies.concat(externalDeps)
|
|
||||||
|
|
||||||
const nodeVMOptions = {
|
|
||||||
console: 'inherit',
|
|
||||||
sandbox,
|
|
||||||
require: {
|
|
||||||
external: { modules: deps },
|
|
||||||
builtin: builtinDeps
|
|
||||||
},
|
|
||||||
eval: false,
|
|
||||||
wasm: false,
|
|
||||||
timeout: 10000
|
|
||||||
} as any
|
|
||||||
|
|
||||||
const vm = new NodeVM(nodeVMOptions)
|
|
||||||
try {
|
try {
|
||||||
const responseTrue = await vm.run(`module.exports = async function() {${ifFunction}}()`, __dirname)
|
const responseTrue = await executeJavaScriptCode(ifFunction, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
if (responseTrue)
|
if (responseTrue)
|
||||||
return { output: typeof responseTrue === 'string' ? handleEscapeCharacters(responseTrue, false) : responseTrue, type: true }
|
return { output: typeof responseTrue === 'string' ? handleEscapeCharacters(responseTrue, false) : responseTrue, type: true }
|
||||||
|
|
||||||
const responseFalse = await vm.run(`module.exports = async function() {${elseFunction}}()`, __dirname)
|
const responseFalse = await executeJavaScriptCode(elseFunction, sandbox, {
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
return { output: typeof responseFalse === 'string' ? handleEscapeCharacters(responseFalse, false) : responseFalse, type: false }
|
return { output: typeof responseFalse === 'string' ? handleEscapeCharacters(responseFalse, false) : responseFalse, type: false }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(e)
|
throw new Error(e)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
"@aws-sdk/client-secrets-manager": "^3.699.0",
|
"@aws-sdk/client-secrets-manager": "^3.699.0",
|
||||||
"@datastax/astra-db-ts": "1.5.0",
|
"@datastax/astra-db-ts": "1.5.0",
|
||||||
"@dqbd/tiktoken": "^1.0.21",
|
"@dqbd/tiktoken": "^1.0.21",
|
||||||
"@e2b/code-interpreter": "^0.0.5",
|
"@e2b/code-interpreter": "^1.5.1",
|
||||||
"@elastic/elasticsearch": "^8.9.0",
|
"@elastic/elasticsearch": "^8.9.0",
|
||||||
"@flowiseai/nodevm": "^3.9.25",
|
"@flowiseai/nodevm": "^3.9.25",
|
||||||
"@getzep/zep-cloud": "~1.0.7",
|
"@getzep/zep-cloud": "~1.0.7",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ import { GetSecretValueCommand, SecretsManagerClient, SecretsManagerClientConfig
|
||||||
import { customGet } from '../nodes/sequentialagents/commonUtils'
|
import { customGet } from '../nodes/sequentialagents/commonUtils'
|
||||||
import { TextSplitter } from 'langchain/text_splitter'
|
import { TextSplitter } from 'langchain/text_splitter'
|
||||||
import { DocumentLoader } from 'langchain/document_loaders/base'
|
import { DocumentLoader } from 'langchain/document_loaders/base'
|
||||||
|
import { NodeVM } from '@flowiseai/nodevm'
|
||||||
|
import { Sandbox } from '@e2b/code-interpreter'
|
||||||
|
|
||||||
export const numberOrExpressionRegex = '^(\\d+\\.?\\d*|{{.*}})$' //return true if string consists only numbers OR expression {{}}
|
export const numberOrExpressionRegex = '^(\\d+\\.?\\d*|{{.*}})$' //return true if string consists only numbers OR expression {{}}
|
||||||
export const notEmptyRegex = '(.|\\s)*\\S(.|\\s)*' //return true if string is not empty or blank
|
export const notEmptyRegex = '(.|\\s)*\\S(.|\\s)*' //return true if string is not empty or blank
|
||||||
|
|
@ -1348,3 +1350,227 @@ export const stripHTMLFromToolInput = (input: string) => {
|
||||||
cleanedInput = cleanedInput.replace(/\\_/g, '_')
|
cleanedInput = cleanedInput.replace(/\\_/g, '_')
|
||||||
return cleanedInput
|
return cleanedInput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function to convert require statements to ESM imports
|
||||||
|
const convertRequireToImport = (requireLine: string): string | null => {
|
||||||
|
// Remove leading/trailing whitespace and get the indentation
|
||||||
|
const indent = requireLine.match(/^(\s*)/)?.[1] || ''
|
||||||
|
const trimmed = requireLine.trim()
|
||||||
|
|
||||||
|
// Match patterns like: const/let/var name = require('module')
|
||||||
|
const defaultRequireMatch = trimmed.match(/^(const|let|var)\s+(\w+)\s*=\s*require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/)
|
||||||
|
if (defaultRequireMatch) {
|
||||||
|
const [, , varName, moduleName] = defaultRequireMatch
|
||||||
|
return `${indent}import ${varName} from '${moduleName}';`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match patterns like: const { name1, name2 } = require('module')
|
||||||
|
const destructureMatch = trimmed.match(/^(const|let|var)\s+\{\s*([^}]+)\s*\}\s*=\s*require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/)
|
||||||
|
if (destructureMatch) {
|
||||||
|
const [, , destructuredVars, moduleName] = destructureMatch
|
||||||
|
return `${indent}import { ${destructuredVars.trim()} } from '${moduleName}';`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match patterns like: const name = require('module').property
|
||||||
|
const propertyMatch = trimmed.match(/^(const|let|var)\s+(\w+)\s*=\s*require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)\.(\w+)/)
|
||||||
|
if (propertyMatch) {
|
||||||
|
const [, , varName, moduleName, property] = propertyMatch
|
||||||
|
return `${indent}import { ${property} as ${varName} } from '${moduleName}';`
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no pattern matches, return null to skip conversion
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute JavaScript code using either Sandbox or NodeVM
|
||||||
|
* @param {string} code - The JavaScript code to execute
|
||||||
|
* @param {ICommonObject} sandbox - The sandbox object with variables
|
||||||
|
* @param {ICommonObject} options - Execution options
|
||||||
|
* @returns {Promise<any>} - The execution result
|
||||||
|
*/
|
||||||
|
export const executeJavaScriptCode = async (
|
||||||
|
code: string,
|
||||||
|
sandbox: ICommonObject,
|
||||||
|
options: {
|
||||||
|
timeout?: number
|
||||||
|
useSandbox?: boolean
|
||||||
|
libraries?: string[]
|
||||||
|
streamOutput?: (output: string) => void
|
||||||
|
nodeVMOptions?: ICommonObject
|
||||||
|
} = {}
|
||||||
|
): Promise<any> => {
|
||||||
|
const { timeout = 10000, useSandbox = true, streamOutput, libraries = [], nodeVMOptions = {} } = options
|
||||||
|
const shouldUseSandbox = useSandbox && process.env.E2B_APIKEY
|
||||||
|
|
||||||
|
if (shouldUseSandbox) {
|
||||||
|
try {
|
||||||
|
const variableDeclarations = []
|
||||||
|
|
||||||
|
if (sandbox['$vars']) {
|
||||||
|
variableDeclarations.push(`const $vars = ${JSON.stringify(sandbox['$vars'])};`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sandbox['$flow']) {
|
||||||
|
variableDeclarations.push(`const $flow = ${JSON.stringify(sandbox['$flow'])};`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add other sandbox variables
|
||||||
|
for (const [key, value] of Object.entries(sandbox)) {
|
||||||
|
if (
|
||||||
|
key !== '$vars' &&
|
||||||
|
key !== '$flow' &&
|
||||||
|
key !== 'util' &&
|
||||||
|
key !== 'Symbol' &&
|
||||||
|
key !== 'child_process' &&
|
||||||
|
key !== 'fs' &&
|
||||||
|
key !== 'process'
|
||||||
|
) {
|
||||||
|
variableDeclarations.push(`const ${key} = ${JSON.stringify(value)};`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle import statements properly - they must be at the top
|
||||||
|
const lines = code.split('\n')
|
||||||
|
const importLines = []
|
||||||
|
const otherLines = []
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const trimmedLine = line.trim()
|
||||||
|
|
||||||
|
// Skip node-fetch imports since Node.js has built-in fetch
|
||||||
|
if (trimmedLine.includes('node-fetch') || trimmedLine.includes("'fetch'") || trimmedLine.includes('"fetch"')) {
|
||||||
|
continue // Skip this line entirely
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for existing ES6 imports and exports
|
||||||
|
if (trimmedLine.startsWith('import ') || trimmedLine.startsWith('export ')) {
|
||||||
|
importLines.push(line)
|
||||||
|
}
|
||||||
|
// Check for CommonJS require statements and convert them to ESM imports
|
||||||
|
else if (/^(const|let|var)\s+.*=\s*require\s*\(/.test(trimmedLine)) {
|
||||||
|
const convertedImport = convertRequireToImport(trimmedLine)
|
||||||
|
if (convertedImport) {
|
||||||
|
importLines.push(convertedImport)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
otherLines.push(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sbx = await Sandbox.create({ apiKey: process.env.E2B_APIKEY })
|
||||||
|
|
||||||
|
// Install libraries
|
||||||
|
for (const library of libraries) {
|
||||||
|
await sbx.commands.run(`npm install ${library}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate imports from the rest of the code for proper ES6 module structure
|
||||||
|
const codeWithImports = [
|
||||||
|
...importLines,
|
||||||
|
`module.exports = async function() {`,
|
||||||
|
...variableDeclarations,
|
||||||
|
...otherLines,
|
||||||
|
`}()`
|
||||||
|
].join('\n')
|
||||||
|
|
||||||
|
const execution = await sbx.runCode(codeWithImports, { language: 'js' })
|
||||||
|
|
||||||
|
let output = ''
|
||||||
|
|
||||||
|
if (execution.text) output = execution.text
|
||||||
|
if (!execution.text && execution.logs.stdout.length) output = execution.logs.stdout.join('\n')
|
||||||
|
|
||||||
|
if (execution.error) {
|
||||||
|
throw new Error(`${execution.error.name}: ${execution.error.value}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (execution.logs.stderr.length) {
|
||||||
|
throw new Error(execution.logs.stderr.join('\n'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stream output if streaming function provided
|
||||||
|
if (streamOutput && output) {
|
||||||
|
streamOutput(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up sandbox
|
||||||
|
sbx.kill()
|
||||||
|
|
||||||
|
return output
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Sandbox Execution Error: ${e}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const builtinDeps = process.env.TOOL_FUNCTION_BUILTIN_DEP
|
||||||
|
? defaultAllowBuiltInDep.concat(process.env.TOOL_FUNCTION_BUILTIN_DEP.split(','))
|
||||||
|
: defaultAllowBuiltInDep
|
||||||
|
const externalDeps = process.env.TOOL_FUNCTION_EXTERNAL_DEP ? process.env.TOOL_FUNCTION_EXTERNAL_DEP.split(',') : []
|
||||||
|
const deps = availableDependencies.concat(externalDeps)
|
||||||
|
|
||||||
|
const defaultNodeVMOptions: any = {
|
||||||
|
console: 'inherit',
|
||||||
|
sandbox,
|
||||||
|
require: {
|
||||||
|
external: { modules: deps },
|
||||||
|
builtin: builtinDeps
|
||||||
|
},
|
||||||
|
eval: false,
|
||||||
|
wasm: false,
|
||||||
|
timeout
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge with custom nodeVMOptions if provided
|
||||||
|
const finalNodeVMOptions = { ...defaultNodeVMOptions, ...nodeVMOptions }
|
||||||
|
|
||||||
|
const vm = new NodeVM(finalNodeVMOptions)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await vm.run(`module.exports = async function() {${code}}()`, __dirname)
|
||||||
|
|
||||||
|
let finalOutput = response
|
||||||
|
if (typeof response === 'object') {
|
||||||
|
finalOutput = JSON.stringify(response, null, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stream output if streaming function provided
|
||||||
|
if (streamOutput && finalOutput) {
|
||||||
|
streamOutput(finalOutput)
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalOutput
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`NodeVM Execution Error: ${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a standard sandbox object for code execution
|
||||||
|
* @param {string} input - The input string
|
||||||
|
* @param {ICommonObject} variables - Variables from getVars
|
||||||
|
* @param {ICommonObject} flow - Flow object with chatflowId, sessionId, etc.
|
||||||
|
* @param {ICommonObject} additionalSandbox - Additional sandbox variables
|
||||||
|
* @returns {ICommonObject} - The sandbox object
|
||||||
|
*/
|
||||||
|
export const createCodeExecutionSandbox = (
|
||||||
|
input: string,
|
||||||
|
variables: IVariable[],
|
||||||
|
flow: ICommonObject,
|
||||||
|
additionalSandbox: ICommonObject = {}
|
||||||
|
): ICommonObject => {
|
||||||
|
const sandbox: ICommonObject = {
|
||||||
|
$input: input,
|
||||||
|
util: undefined,
|
||||||
|
Symbol: undefined,
|
||||||
|
child_process: undefined,
|
||||||
|
fs: undefined,
|
||||||
|
process: undefined,
|
||||||
|
...additionalSandbox
|
||||||
|
}
|
||||||
|
|
||||||
|
sandbox['$vars'] = prepareSandboxVars(variables)
|
||||||
|
sandbox['$flow'] = flow
|
||||||
|
|
||||||
|
return sandbox
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,20 @@ export const isValidUUID = (uuid: string): boolean => {
|
||||||
return uuidV4Pattern.test(uuid)
|
return uuidV4Pattern.test(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates if a string is a valid URL
|
||||||
|
* @param {string} url The string to validate
|
||||||
|
* @returns {boolean} True if valid URL, false otherwise
|
||||||
|
*/
|
||||||
|
export const isValidURL = (url: string): boolean => {
|
||||||
|
try {
|
||||||
|
new URL(url)
|
||||||
|
return true
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates if a string contains path traversal attempts
|
* Validates if a string contains path traversal attempts
|
||||||
* @param {string} path The string to validate
|
* @param {string} path The string to validate
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ const LoaderConfigPreviewChunks = () => {
|
||||||
const previewResp = await documentStoreApi.previewChunks(config)
|
const previewResp = await documentStoreApi.previewChunks(config)
|
||||||
if (previewResp.data) {
|
if (previewResp.data) {
|
||||||
setTotalChunks(previewResp.data.totalChunks)
|
setTotalChunks(previewResp.data.totalChunks)
|
||||||
setDocumentChunks(previewResp.data.chunks)
|
setDocumentChunks(Array.isArray(previewResp.data.chunks) ? previewResp.data.chunks : [])
|
||||||
setCurrentPreviewCount(previewResp.data.previewChunkCount)
|
setCurrentPreviewCount(previewResp.data.previewChunkCount)
|
||||||
}
|
}
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,8 @@ importers:
|
||||||
specifier: ^1.0.21
|
specifier: ^1.0.21
|
||||||
version: 1.0.21
|
version: 1.0.21
|
||||||
'@e2b/code-interpreter':
|
'@e2b/code-interpreter':
|
||||||
specifier: ^0.0.5
|
specifier: ^1.5.1
|
||||||
version: 0.0.5(bufferutil@4.0.8)(utf-8-validate@6.0.4)
|
version: 1.5.1
|
||||||
'@elastic/elasticsearch':
|
'@elastic/elasticsearch':
|
||||||
specifier: ^8.9.0
|
specifier: ^8.9.0
|
||||||
version: 8.12.2
|
version: 8.12.2
|
||||||
|
|
@ -2986,6 +2986,9 @@ packages:
|
||||||
openai: 4.96.0
|
openai: 4.96.0
|
||||||
zod: ^3.23.8
|
zod: ^3.23.8
|
||||||
|
|
||||||
|
'@bufbuild/protobuf@2.6.1':
|
||||||
|
resolution: { integrity: sha512-DaG6XlyKpz08bmHY5SGX2gfIllaqtDJ/KwVoxsmP22COOLYwDBe7yD3DZGwXem/Xq7QOc9cuR7R3MpAv5CFfDw== }
|
||||||
|
|
||||||
'@bull-board/api@6.11.0':
|
'@bull-board/api@6.11.0':
|
||||||
resolution: { integrity: sha512-HLbIuXIthrgeVRmN7Vec9/7ZKWx8i1xTC6Nzi//l7ua+Xu5wn6f/aZllUNVzty5ilLTHqWFkfVOwpuN91o7yxA== }
|
resolution: { integrity: sha512-HLbIuXIthrgeVRmN7Vec9/7ZKWx8i1xTC6Nzi//l7ua+Xu5wn6f/aZllUNVzty5ilLTHqWFkfVOwpuN91o7yxA== }
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
@ -3055,6 +3058,17 @@ packages:
|
||||||
resolution: { integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== }
|
resolution: { integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== }
|
||||||
engines: { node: '>=0.1.90' }
|
engines: { node: '>=0.1.90' }
|
||||||
|
|
||||||
|
'@connectrpc/connect-web@2.0.0-rc.3':
|
||||||
|
resolution: { integrity: sha512-w88P8Lsn5CCsA7MFRl2e6oLY4J/5toiNtJns/YJrlyQaWOy3RO8pDgkz+iIkG98RPMhj2thuBvsd3Cn4DKKCkw== }
|
||||||
|
peerDependencies:
|
||||||
|
'@bufbuild/protobuf': ^2.2.0
|
||||||
|
'@connectrpc/connect': 2.0.0-rc.3
|
||||||
|
|
||||||
|
'@connectrpc/connect@2.0.0-rc.3':
|
||||||
|
resolution: { integrity: sha512-ARBt64yEyKbanyRETTjcjJuHr2YXorzQo0etyS5+P6oSeW8xEuzajA9g+zDnMcj1hlX2dQE93foIWQGfpru7gQ== }
|
||||||
|
peerDependencies:
|
||||||
|
'@bufbuild/protobuf': ^2.2.0
|
||||||
|
|
||||||
'@couchbase/couchbase-darwin-arm64-napi@4.4.1':
|
'@couchbase/couchbase-darwin-arm64-napi@4.4.1':
|
||||||
resolution: { integrity: sha512-YHS0TDrXe+S3nKywjZ/11Ia+25l5DypXYdyeOf4/le+zsJomnR5E3w4h1RaZ669/gvR8ltyOJn6TG//VDSp6qg== }
|
resolution: { integrity: sha512-YHS0TDrXe+S3nKywjZ/11Ia+25l5DypXYdyeOf4/le+zsJomnR5E3w4h1RaZ669/gvR8ltyOJn6TG//VDSp6qg== }
|
||||||
engines: { node: '>=16' }
|
engines: { node: '>=16' }
|
||||||
|
|
@ -3215,8 +3229,8 @@ packages:
|
||||||
'@dqbd/tiktoken@1.0.21':
|
'@dqbd/tiktoken@1.0.21':
|
||||||
resolution: { integrity: sha512-grBxRSY9+/iBM205EWjbMm5ySeXQrhJyXWMP38VJd+pO2DRGraDAbi4n8J8T9M4XY1M/FHgonMcmu3J+KjcX0Q== }
|
resolution: { integrity: sha512-grBxRSY9+/iBM205EWjbMm5ySeXQrhJyXWMP38VJd+pO2DRGraDAbi4n8J8T9M4XY1M/FHgonMcmu3J+KjcX0Q== }
|
||||||
|
|
||||||
'@e2b/code-interpreter@0.0.5':
|
'@e2b/code-interpreter@1.5.1':
|
||||||
resolution: { integrity: sha512-ToFQ6N6EU8t91z3EJzh+mG+zf7uK8I1PRLWeu1f3bPS0pAJfM0puzBWOB3XlF9A9R5zZu/g8iO1gGPQXzXY5vA== }
|
resolution: { integrity: sha512-mkyKjAW2KN5Yt0R1I+1lbH3lo+W/g/1+C2lnwlitXk5wqi/g94SEO41XKdmDf5WWpKG3mnxWDR5d6S/lyjmMEw== }
|
||||||
engines: { node: '>=18' }
|
engines: { node: '>=18' }
|
||||||
|
|
||||||
'@elastic/elasticsearch@8.12.2':
|
'@elastic/elasticsearch@8.12.2':
|
||||||
|
|
@ -9112,6 +9126,9 @@ packages:
|
||||||
commondir@1.0.1:
|
commondir@1.0.1:
|
||||||
resolution: { integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== }
|
resolution: { integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== }
|
||||||
|
|
||||||
|
compare-versions@6.1.1:
|
||||||
|
resolution: { integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg== }
|
||||||
|
|
||||||
component-emitter@1.3.1:
|
component-emitter@1.3.1:
|
||||||
resolution: { integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== }
|
resolution: { integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== }
|
||||||
|
|
||||||
|
|
@ -9980,8 +9997,8 @@ packages:
|
||||||
duplexify@4.1.3:
|
duplexify@4.1.3:
|
||||||
resolution: { integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== }
|
resolution: { integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== }
|
||||||
|
|
||||||
e2b@0.16.1:
|
e2b@1.9.0:
|
||||||
resolution: { integrity: sha512-2L1R/REEB+EezD4Q4MmcXXNATjvCYov2lv/69+PY6V95+wl1PZblIMTYAe7USxX6P6sqANxNs+kXqZr6RvXkSw== }
|
resolution: { integrity: sha512-MM3RhWW7YENYocTy20BvKVcn8li/FxkDrHINS7tmz00ffl1ZavQTRxCI9Sl8ofeRg+HVMlqO4W8LJ+ij9VTZPg== }
|
||||||
engines: { node: '>=18' }
|
engines: { node: '>=18' }
|
||||||
|
|
||||||
each-props@1.3.2:
|
each-props@1.3.2:
|
||||||
|
|
@ -11986,11 +12003,6 @@ packages:
|
||||||
isomorphic-fetch@3.0.0:
|
isomorphic-fetch@3.0.0:
|
||||||
resolution: { integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== }
|
resolution: { integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== }
|
||||||
|
|
||||||
isomorphic-ws@5.0.0:
|
|
||||||
resolution: { integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== }
|
|
||||||
peerDependencies:
|
|
||||||
ws: 8.18.3
|
|
||||||
|
|
||||||
isstream@0.1.2:
|
isstream@0.1.2:
|
||||||
resolution: { integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== }
|
resolution: { integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== }
|
||||||
|
|
||||||
|
|
@ -13913,12 +13925,14 @@ packages:
|
||||||
zod:
|
zod:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
openapi-fetch@0.9.8:
|
||||||
|
resolution: { integrity: sha512-zM6elH0EZStD/gSiNlcPrzXcVQ/pZo3BDvC6CDwRDUt1dDzxlshpmQnpD6cZaJ39THaSmwVCxxRrPKNM1hHrDg== }
|
||||||
|
|
||||||
openapi-types@12.1.3:
|
openapi-types@12.1.3:
|
||||||
resolution: { integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== }
|
resolution: { integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw== }
|
||||||
|
|
||||||
openapi-typescript-fetch@1.1.3:
|
openapi-typescript-helpers@0.0.8:
|
||||||
resolution: { integrity: sha512-smLZPck4OkKMNExcw8jMgrMOGgVGx2N/s6DbKL2ftNl77g5HfoGpZGFy79RBzU/EkaO0OZpwBnslfdBfh7ZcWg== }
|
resolution: { integrity: sha512-1eNjQtbfNi5Z/kFhagDIaIRj6qqDzhjNJKz8cmMW0CVdGwT6e1GLbAfgI0d28VTJa1A8jz82jm/4dG8qNoNS8g== }
|
||||||
engines: { node: '>= 12.0.0', npm: '>= 7.0.0' }
|
|
||||||
|
|
||||||
option@0.2.4:
|
option@0.2.4:
|
||||||
resolution: { integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A== }
|
resolution: { integrity: sha512-pkEqbDyl8ou5cpq+VsnQbe/WlEy5qS7xPzMS1U55OCG9KPvwFD46zDbxQIj3egJSFc3D+XhYOPUzz49zQAVy7A== }
|
||||||
|
|
@ -14129,9 +14143,6 @@ packages:
|
||||||
resolution: { integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== }
|
resolution: { integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== }
|
||||||
engines: { node: '>= 0.4.0' }
|
engines: { node: '>= 0.4.0' }
|
||||||
|
|
||||||
path-browserify@1.0.1:
|
|
||||||
resolution: { integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== }
|
|
||||||
|
|
||||||
path-case@3.0.4:
|
path-case@3.0.4:
|
||||||
resolution: { integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== }
|
resolution: { integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== }
|
||||||
|
|
||||||
|
|
@ -21776,6 +21787,8 @@ snapshots:
|
||||||
- encoding
|
- encoding
|
||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
|
|
||||||
|
'@bufbuild/protobuf@2.6.1': {}
|
||||||
|
|
||||||
'@bull-board/api@6.11.0(@bull-board/ui@6.11.0)':
|
'@bull-board/api@6.11.0(@bull-board/ui@6.11.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@bull-board/ui': 6.11.0
|
'@bull-board/ui': 6.11.0
|
||||||
|
|
@ -21905,6 +21918,15 @@ snapshots:
|
||||||
|
|
||||||
'@colors/colors@1.6.0': {}
|
'@colors/colors@1.6.0': {}
|
||||||
|
|
||||||
|
'@connectrpc/connect-web@2.0.0-rc.3(@bufbuild/protobuf@2.6.1)(@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.6.1))':
|
||||||
|
dependencies:
|
||||||
|
'@bufbuild/protobuf': 2.6.1
|
||||||
|
'@connectrpc/connect': 2.0.0-rc.3(@bufbuild/protobuf@2.6.1)
|
||||||
|
|
||||||
|
'@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.6.1)':
|
||||||
|
dependencies:
|
||||||
|
'@bufbuild/protobuf': 2.6.1
|
||||||
|
|
||||||
'@couchbase/couchbase-darwin-arm64-napi@4.4.1':
|
'@couchbase/couchbase-darwin-arm64-napi@4.4.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
|
@ -22057,14 +22079,9 @@ snapshots:
|
||||||
|
|
||||||
'@dqbd/tiktoken@1.0.21': {}
|
'@dqbd/tiktoken@1.0.21': {}
|
||||||
|
|
||||||
'@e2b/code-interpreter@0.0.5(bufferutil@4.0.8)(utf-8-validate@6.0.4)':
|
'@e2b/code-interpreter@1.5.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
e2b: 0.16.1
|
e2b: 1.9.0
|
||||||
isomorphic-ws: 5.0.0(ws@8.18.3(bufferutil@4.0.8)(utf-8-validate@6.0.4))
|
|
||||||
ws: 8.18.3(bufferutil@4.0.8)(utf-8-validate@6.0.4)
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- bufferutil
|
|
||||||
- utf-8-validate
|
|
||||||
|
|
||||||
'@elastic/elasticsearch@8.12.2':
|
'@elastic/elasticsearch@8.12.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -29305,6 +29322,8 @@ snapshots:
|
||||||
|
|
||||||
commondir@1.0.1: {}
|
commondir@1.0.1: {}
|
||||||
|
|
||||||
|
compare-versions@6.1.1: {}
|
||||||
|
|
||||||
component-emitter@1.3.1: {}
|
component-emitter@1.3.1: {}
|
||||||
|
|
||||||
component-register@0.8.3: {}
|
component-register@0.8.3: {}
|
||||||
|
|
@ -30249,17 +30268,14 @@ snapshots:
|
||||||
readable-stream: 3.6.2
|
readable-stream: 3.6.2
|
||||||
stream-shift: 1.0.3
|
stream-shift: 1.0.3
|
||||||
|
|
||||||
e2b@0.16.1:
|
e2b@1.9.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
isomorphic-ws: 5.0.0(ws@8.18.3(bufferutil@4.0.8)(utf-8-validate@6.0.4))
|
'@bufbuild/protobuf': 2.6.1
|
||||||
normalize-path: 3.0.0
|
'@connectrpc/connect': 2.0.0-rc.3(@bufbuild/protobuf@2.6.1)
|
||||||
openapi-typescript-fetch: 1.1.3
|
'@connectrpc/connect-web': 2.0.0-rc.3(@bufbuild/protobuf@2.6.1)(@connectrpc/connect@2.0.0-rc.3(@bufbuild/protobuf@2.6.1))
|
||||||
path-browserify: 1.0.1
|
compare-versions: 6.1.1
|
||||||
|
openapi-fetch: 0.9.8
|
||||||
platform: 1.3.6
|
platform: 1.3.6
|
||||||
ws: 8.18.3(bufferutil@4.0.8)(utf-8-validate@6.0.4)
|
|
||||||
optionalDependencies:
|
|
||||||
bufferutil: 4.0.8
|
|
||||||
utf-8-validate: 6.0.4
|
|
||||||
|
|
||||||
each-props@1.3.2:
|
each-props@1.3.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
@ -32971,10 +32987,6 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
|
|
||||||
isomorphic-ws@5.0.0(ws@8.18.3(bufferutil@4.0.8)(utf-8-validate@6.0.4)):
|
|
||||||
dependencies:
|
|
||||||
ws: 8.18.3(bufferutil@4.0.8)(utf-8-validate@6.0.4)
|
|
||||||
|
|
||||||
isstream@0.1.2: {}
|
isstream@0.1.2: {}
|
||||||
|
|
||||||
istanbul-lib-coverage@3.2.2: {}
|
istanbul-lib-coverage@3.2.2: {}
|
||||||
|
|
@ -35818,9 +35830,13 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
|
|
||||||
|
openapi-fetch@0.9.8:
|
||||||
|
dependencies:
|
||||||
|
openapi-typescript-helpers: 0.0.8
|
||||||
|
|
||||||
openapi-types@12.1.3: {}
|
openapi-types@12.1.3: {}
|
||||||
|
|
||||||
openapi-typescript-fetch@1.1.3: {}
|
openapi-typescript-helpers@0.0.8: {}
|
||||||
|
|
||||||
option@0.2.4: {}
|
option@0.2.4: {}
|
||||||
|
|
||||||
|
|
@ -36070,8 +36086,6 @@ snapshots:
|
||||||
pause: 0.0.1
|
pause: 0.0.1
|
||||||
utils-merge: 1.0.1
|
utils-merge: 1.0.1
|
||||||
|
|
||||||
path-browserify@1.0.1: {}
|
|
||||||
|
|
||||||
path-case@3.0.4:
|
path-case@3.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
dot-case: 3.0.4
|
dot-case: 3.0.4
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue