Enable/disable variables in override configuration (#3467)

* Add ability to enable/disable which variables can be overriden during external predictions

* Remove duplicated code

* Remove rate limit and allowed domains tab from chatflow configuration

* Show tooltip in api code dialog for override config properties

* Fix server crash when override config is not available

* update UI for chatflow config security, file upload

* Fix UI issues in security tab of chatflow configuration dialog

* Fix override config options not updating when nodes change

* Fix crash in api code dialog when overrideConfig is not available for a chatflow/agentflow. Also fix input config in api code dialog not updating when nodes change.

* Refactor override config and add override config for variables

* Update api code dialog - update how override config is read and show variable overrides

* Update how node and variable overrides are read and resolved

* Prevent api code dialog mounting on page load and only mount when api code dialog button is clicked. this should fix loading incorrect data.

* Fix variables list not showing when overrideConfig is not available

* add overrideconfig to agentflow and upsert vector

* temporarily removed enable overrideconfig on upsert, fix linting issues

---------

Co-authored-by: Henry <hzj94@hotmail.com>
This commit is contained in:
Ilango
2024-11-13 23:51:59 +05:30
committed by GitHub
parent 3b72017a10
commit 537aa51ef8
16 changed files with 1053 additions and 289 deletions
+61 -11
View File
@@ -2,6 +2,7 @@ import path from 'path'
import fs from 'fs'
import logger from './logger'
import {
IChatFlow,
IComponentCredentials,
IComponentNodes,
ICredentialDataDecrypted,
@@ -434,6 +435,9 @@ type BuildFlowParams = {
apiMessageId: string
appDataSource: DataSource
overrideConfig?: ICommonObject
apiOverrideStatus?: boolean
nodeOverrides?: ICommonObject
variableOverrides?: ICommonObject[]
cachePool?: CachePool
isUpsert?: boolean
stopNodeId?: string
@@ -462,6 +466,9 @@ export const buildFlow = async ({
chatflowid,
appDataSource,
overrideConfig,
apiOverrideStatus = false,
nodeOverrides = {},
variableOverrides = [],
cachePool,
isUpsert,
stopNodeId,
@@ -509,7 +516,11 @@ export const buildFlow = async ({
const newNodeInstance = new nodeModule.nodeClass()
let flowNodeData = cloneDeep(reactFlowNode.data)
if (overrideConfig) flowNodeData = replaceInputsWithConfig(flowNodeData, overrideConfig)
// Only override the config if its status is true
if (overrideConfig && apiOverrideStatus) {
flowNodeData = replaceInputsWithConfig(flowNodeData, overrideConfig, nodeOverrides)
}
if (isUpsert) upsertHistory['flowData'] = saveUpsertFlowData(flowNodeData, upsertHistory)
@@ -520,7 +531,8 @@ export const buildFlow = async ({
question,
chatHistory,
flowData,
uploadedFilesContent
uploadedFilesContent,
variableOverrides
)
if (isUpsert && stopNodeId && nodeId === stopNodeId) {
@@ -713,13 +725,19 @@ export const clearSessionMemory = async (
}
}
const getGlobalVariable = async (appDataSource: DataSource, overrideConfig?: ICommonObject) => {
const getGlobalVariable = async (appDataSource: DataSource, overrideConfig?: ICommonObject, variableOverrides?: ICommonObject[]) => {
const variables = await appDataSource.getRepository(Variable).find()
// override variables defined in overrideConfig
// nodeData.inputs.vars is an Object, check each property and override the variable
if (overrideConfig?.vars) {
if (overrideConfig?.vars && variableOverrides) {
for (const propertyName of Object.getOwnPropertyNames(overrideConfig.vars)) {
// Check if this variable is enabled for override
const override = variableOverrides.find((v) => v.name === propertyName)
if (!override?.enabled) {
continue // Skip this variable if it's not enabled for override
}
const foundVar = variables.find((v) => v.name === propertyName)
if (foundVar) {
// even if the variable was defined as runtime, we override it with static value
@@ -776,7 +794,8 @@ export const getVariableValue = async (
chatHistory: IMessage[],
isAcceptVariable = false,
flowData?: ICommonObject,
uploadedFilesContent?: string
uploadedFilesContent?: string,
variableOverrides: ICommonObject[] = []
) => {
const isObject = typeof paramValue === 'object'
const initialValue = (isObject ? JSON.stringify(paramValue) : paramValue) ?? ''
@@ -818,7 +837,7 @@ export const getVariableValue = async (
}
if (variableFullPath.startsWith('$vars.')) {
const vars = await getGlobalVariable(appDataSource, flowData)
const vars = await getGlobalVariable(appDataSource, flowData, variableOverrides)
const variableValue = get(vars, variableFullPath.replace('$vars.', ''))
if (variableValue) {
variableDict[`{{${variableFullPath}}}`] = variableValue
@@ -927,7 +946,8 @@ export const resolveVariables = async (
question: string,
chatHistory: IMessage[],
flowData?: ICommonObject,
uploadedFilesContent?: string
uploadedFilesContent?: string,
variableOverrides: ICommonObject[] = []
): Promise<INodeData> => {
let flowNodeData = cloneDeep(reactFlowNodeData)
const types = 'inputs'
@@ -946,7 +966,8 @@ export const resolveVariables = async (
chatHistory,
undefined,
flowData,
uploadedFilesContent
uploadedFilesContent,
variableOverrides
)
resolvedInstances.push(resolvedInstance)
}
@@ -961,7 +982,8 @@ export const resolveVariables = async (
chatHistory,
isAcceptVariable,
flowData,
uploadedFilesContent
uploadedFilesContent,
variableOverrides
)
paramsObj[key] = resolvedInstance
}
@@ -978,18 +1000,28 @@ export const resolveVariables = async (
* Loop through each inputs and replace their value with override config values
* @param {INodeData} flowNodeData
* @param {ICommonObject} overrideConfig
* @param {ICommonObject} nodeOverrides
* @returns {INodeData}
*/
export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig: ICommonObject) => {
export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig: ICommonObject, nodeOverrides: ICommonObject) => {
const types = 'inputs'
const isParameterEnabled = (nodeType: string, paramName: string): boolean => {
if (!nodeOverrides[nodeType]) return false
const parameter = nodeOverrides[nodeType].find((param: any) => param.name === paramName)
return parameter?.enabled ?? false
}
const getParamValues = (inputsObj: ICommonObject) => {
for (const config in overrideConfig) {
// If overrideConfig[key] is object
if (overrideConfig[config] && typeof overrideConfig[config] === 'object') {
const nodeIds = Object.keys(overrideConfig[config])
if (nodeIds.includes(flowNodeData.id)) {
inputsObj[config] = overrideConfig[config][flowNodeData.id]
// Check if this parameter is enabled for this node type
if (isParameterEnabled(flowNodeData.label, config)) {
inputsObj[config] = overrideConfig[config][flowNodeData.id]
}
continue
} else if (nodeIds.some((nodeId) => nodeId.includes(flowNodeData.name))) {
/*
@@ -1001,6 +1033,11 @@ export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig:
}
}
// Only proceed if the parameter is enabled for this node type
if (!isParameterEnabled(flowNodeData.label, config)) {
continue
}
let paramValue = inputsObj[config]
const overrideConfigValue = overrideConfig[config]
if (overrideConfigValue) {
@@ -1600,3 +1637,16 @@ export const aMonthAgo = () => {
date.setMonth(new Date().getMonth() - 1)
return date
}
export const getAPIOverrideConfig = (chatflow: IChatFlow) => {
try {
const apiConfig = chatflow.apiConfig ? JSON.parse(chatflow.apiConfig) : {}
const nodeOverrides = apiConfig.overrideConfig && apiConfig.overrideConfig.nodes ? apiConfig.overrideConfig.nodes : {}
const variableOverrides = apiConfig.overrideConfig && apiConfig.overrideConfig.variables ? apiConfig.overrideConfig.variables : []
const apiOverrideStatus = apiConfig.overrideConfig && apiConfig.overrideConfig.status ? apiConfig.overrideConfig.status : false
return { nodeOverrides, variableOverrides, apiOverrideStatus }
} catch (error) {
return { nodeOverrides: {}, variableOverrides: [], apiOverrideStatus: false }
}
}