mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-28 11:00:55 +03:00
Merge branch 'main' into feature/Credential
# Conflicts: # README.md # docker/.env.example # packages/components/nodes/documentloaders/Notion/NotionDB.ts # packages/components/nodes/memory/DynamoDb/DynamoDb.ts # packages/components/nodes/memory/MotorheadMemory/MotorheadMemory.ts # packages/components/nodes/memory/ZepMemory/ZepMemory.ts # packages/components/package.json # packages/components/src/utils.ts # packages/server/.env.example # packages/server/README.md # packages/server/marketplaces/chatflows/Conversational Retrieval QA Chain.json # packages/server/src/ChildProcess.ts # packages/server/src/DataSource.ts # packages/server/src/commands/start.ts # packages/server/src/index.ts # packages/server/src/utils/index.ts # packages/server/src/utils/logger.ts
This commit is contained in:
@@ -7,7 +7,7 @@ dotenv.config({ path: path.join(__dirname, '..', '..', '.env'), override: true }
|
||||
|
||||
// default config
|
||||
const loggingConfig = {
|
||||
dir: process.env.LOG_PATH ?? path.join(__dirname, '..', '..', '..', '..', 'logs'),
|
||||
dir: process.env.LOG_PATH ?? path.join(__dirname, '..', '..', 'logs'),
|
||||
server: {
|
||||
level: process.env.LOG_LEVEL ?? 'info',
|
||||
filename: 'server.log',
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
ICredentialReqBody
|
||||
} from '../Interface'
|
||||
import { cloneDeep, get, omit, merge } from 'lodash'
|
||||
import { ICommonObject, getInputVariables, IDatabaseEntity } from 'flowise-components'
|
||||
import { ICommonObject, getInputVariables, IDatabaseEntity, handleEscapeCharacters } from 'flowise-components'
|
||||
import { scryptSync, randomBytes, timingSafeEqual } from 'crypto'
|
||||
import { lib, PBKDF2, AES, enc } from 'crypto-js'
|
||||
|
||||
@@ -281,6 +281,29 @@ export const buildLangchain = async (
|
||||
return flowNodes
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear memory
|
||||
* @param {IReactFlowNode[]} reactFlowNodes
|
||||
* @param {IComponentNodes} componentNodes
|
||||
* @param {string} chatId
|
||||
* @param {string} sessionId
|
||||
*/
|
||||
export const clearSessionMemory = async (
|
||||
reactFlowNodes: IReactFlowNode[],
|
||||
componentNodes: IComponentNodes,
|
||||
chatId: string,
|
||||
sessionId?: string
|
||||
) => {
|
||||
for (const node of reactFlowNodes) {
|
||||
if (node.data.category !== 'Memory') continue
|
||||
const nodeInstanceFilePath = componentNodes[node.data.name].filePath as string
|
||||
const nodeModule = await import(nodeInstanceFilePath)
|
||||
const newNodeInstance = new nodeModule.nodeClass()
|
||||
if (sessionId && node.data.inputs) node.data.inputs.sessionId = sessionId
|
||||
if (newNodeInstance.clearSessionMemory) await newNodeInstance?.clearSessionMemory(node.data, { chatId })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variable value from outputResponses.output
|
||||
* @param {string} paramValue
|
||||
@@ -310,8 +333,13 @@ export const getVariableValue = (paramValue: string, reactFlowNodes: IReactFlowN
|
||||
const variableEndIdx = startIdx
|
||||
const variableFullPath = returnVal.substring(variableStartIdx, variableEndIdx)
|
||||
|
||||
/**
|
||||
* Apply string transformation to convert special chars:
|
||||
* FROM: hello i am ben\n\n\thow are you?
|
||||
* TO: hello i am benFLOWISE_NEWLINEFLOWISE_NEWLINEFLOWISE_TABhow are you?
|
||||
*/
|
||||
if (isAcceptVariable && variableFullPath === QUESTION_VAR_PREFIX) {
|
||||
variableDict[`{{${variableFullPath}}}`] = question
|
||||
variableDict[`{{${variableFullPath}}}`] = handleEscapeCharacters(question, false)
|
||||
}
|
||||
|
||||
// Split by first occurrence of '.' to get just nodeId
|
||||
@@ -414,7 +442,11 @@ export const replaceInputsWithConfig = (flowNodeData: INodeData, overrideConfig:
|
||||
|
||||
const getParamValues = (paramsObj: ICommonObject) => {
|
||||
for (const config in overrideConfig) {
|
||||
paramsObj[config] = overrideConfig[config]
|
||||
let paramValue = overrideConfig[config] ?? paramsObj[config]
|
||||
// Check if boolean
|
||||
if (paramValue === 'true') paramValue = true
|
||||
else if (paramValue === 'false') paramValue = false
|
||||
paramsObj[config] = paramValue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,7 +762,7 @@ export const isFlowValidForStream = (reactFlowNodes: IReactFlowNode[], endingNod
|
||||
isValidChainOrAgent = !blacklistChains.includes(endingNodeData.name)
|
||||
} else if (endingNodeData.category === 'Agents') {
|
||||
// Agent that are available to stream
|
||||
const whitelistAgents = ['openAIFunctionAgent']
|
||||
const whitelistAgents = ['openAIFunctionAgent', 'csvAgent', 'airtableAgent']
|
||||
isValidChainOrAgent = whitelistAgents.includes(endingNodeData.name)
|
||||
}
|
||||
|
||||
|
||||
@@ -57,44 +57,47 @@ const logger = createLogger({
|
||||
* this.app.use(expressRequestLogger)
|
||||
*/
|
||||
export function expressRequestLogger(req: Request, res: Response, next: NextFunction): void {
|
||||
const fileLogger = createLogger({
|
||||
format: combine(timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.json(), errors({ stack: true })),
|
||||
defaultMeta: {
|
||||
package: 'server',
|
||||
request: {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
body: req.body,
|
||||
query: req.query,
|
||||
params: req.params,
|
||||
headers: req.headers
|
||||
}
|
||||
},
|
||||
transports: [
|
||||
new transports.File({
|
||||
filename: path.join(logDir, config.logging.express.filename ?? 'server-requests.log.jsonl'),
|
||||
level: config.logging.express.level ?? 'debug'
|
||||
})
|
||||
]
|
||||
})
|
||||
const unwantedLogURLs = ['/api/v1/node-icon/']
|
||||
if (req.url.includes('/api/v1/') && !unwantedLogURLs.some((url) => req.url.includes(url))) {
|
||||
const fileLogger = createLogger({
|
||||
format: combine(timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), format.json(), errors({ stack: true })),
|
||||
defaultMeta: {
|
||||
package: 'server',
|
||||
request: {
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
body: req.body,
|
||||
query: req.query,
|
||||
params: req.params,
|
||||
headers: req.headers
|
||||
}
|
||||
},
|
||||
transports: [
|
||||
new transports.File({
|
||||
filename: path.join(logDir, config.logging.express.filename ?? 'server-requests.log.jsonl'),
|
||||
level: config.logging.express.level ?? 'debug'
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
const getRequestEmoji = (method: string) => {
|
||||
const requetsEmojis: Record<string, string> = {
|
||||
GET: '⬇️',
|
||||
POST: '⬆️',
|
||||
PUT: '🖊',
|
||||
DELETE: '❌',
|
||||
OPTION: '🔗'
|
||||
const getRequestEmoji = (method: string) => {
|
||||
const requetsEmojis: Record<string, string> = {
|
||||
GET: '⬇️',
|
||||
POST: '⬆️',
|
||||
PUT: '🖊',
|
||||
DELETE: '❌',
|
||||
OPTION: '🔗'
|
||||
}
|
||||
|
||||
return requetsEmojis[method] || '?'
|
||||
}
|
||||
|
||||
return requetsEmojis[method] || '?'
|
||||
}
|
||||
|
||||
if (req.method !== 'GET') {
|
||||
fileLogger.info(`${getRequestEmoji(req.method)} ${req.method} ${req.url}`)
|
||||
logger.info(`${getRequestEmoji(req.method)} ${req.method} ${req.url}`)
|
||||
} else {
|
||||
fileLogger.http(`${getRequestEmoji(req.method)} ${req.method} ${req.url}`)
|
||||
if (req.method !== 'GET') {
|
||||
fileLogger.info(`${getRequestEmoji(req.method)} ${req.method} ${req.url}`)
|
||||
logger.info(`${getRequestEmoji(req.method)} ${req.method} ${req.url}`)
|
||||
} else {
|
||||
fileLogger.http(`${getRequestEmoji(req.method)} ${req.method} ${req.url}`)
|
||||
}
|
||||
}
|
||||
|
||||
next()
|
||||
|
||||
Reference in New Issue
Block a user